Назад Зміст


Регулярні вирази (Regex)

Насамперед варто зауважити, що будь-який рядок сам по собі є регулярним виразом. Регулярні вирази є реєстрозалежними, тому рядок з маленької літери вже не буде відповідати цьому ж виразу з великої літери.

Регулярні вирази мають спецсимволи, які потрібно екранувати. Ось їх список: . ^ $ * + ? { } [ ] \ | ( ).

Екранування здійснюється звичайним способом - додаванням \ перед спецсимволом.

У JavaScript регулярні вирази реалізовані окремим об'єктом RegExp та інтегровані у методи рядків.

Існує два синтаксиси для створення регулярного вираження.

Довгий» синтаксис:

regexp = new RegExp("шаблон", "прапори");

І короткий синтаксис, що використовує сліші "/":

regexp = /шаблон/; // без прапорів

regexp = /шаблон/gmi; // з прапорами gmi

Сліши /.../ говорять JavaScript про те, що це регулярне вираження. Вони відіграють ту саму роль, що й лапки для позначення рядків.

Прапори

Приклад 1:

Методи класу String для пошуку за шаблоном

Рядки підтримують чотири методи, що використовують регулярні вирази.

  1. Метод search(). Він приймає як аргумент регулярне вираження і повертає або позицію першого символу знайденого підрядка, або -1, якщо відповідність не знайдено. Наприклад, наступний дзвінок поверне 4:var result = "JavaScript".search(/script/i); // 4
  2. Метод replace().Виконує пошукову операцію із заміною. Він приймає як першого аргументу регулярне вираження, а як другий - рядок заміни. Метод шукає у рядку, на яку він викликаний, відповідність зазначеному шаблону. Якщо регулярний вираз містить прапор g, метод replace() замінює всі знайдені збігу рядком заміни. Інакше він замінює лише перший знайдений збіг.
  3. Метод match() .Він приймає як єдиний аргумент регулярне вираз (або перетворює свій аргумент на регулярний вираз, передавши його конструктору RegExp()) та повертає масив, що містить результати пошуку. Якщо у регулярному виразі встановлено прапор g, метод повертає масив усіх відповідностей, що у рядку. Наприклад: // поверне ["1", "2", "3"]
    var result = "1 плюс 2 і 3".match(/\d+/g);

Об'єкт RegExp

Об'єкти RegExp визначають два методи, що виконують пошук за шаблоном; вони поводяться аналогічно методам класу String, описаним вище.

  1. Метод exec() виконує регулярне вираження для зазначеного рядка, тобто. шукає збіг в рядку. Якщо збіг не виявлено, метод повертає null. Однак якщо відповідність знайдено, він повертає такий самий масив, як масив, що повертається методом match() для пошуку без прапора g. Нульовий елемент масиву містить рядок, що відповідає регулярному виразу, всі наступні елементи - підрядки, відповідні всім подвыражениям. Крім того, властивість index містить номер позиції символу, яким починається відповідний фрагмент, а властивість input посилається на рядок, у якому виконувався пошук.
  2. Метод test() , який набагато простіше методу exec(). Він приймає рядок і повертає true, якщо рядок відповідає регулярному виразу:

Завдання 1:

У наступному прикладі визначається функція, яка виділяє помаранчевим кольором рік у тексті.

Приклад 2

На прикладі показується перевірка правильності адреси IP.

Приклади. Метод replace

Першим параметром цього методу можна передавати не просто рядок, а регулярний вираз. Подивіться різницю:

де_меняем.replace(що міняємо, на що міняємо)

alert( 'bab'.replace('a', '!') ); //виведе 'b!b'
alert( 'bab'.replace(/a/g, '!') ); //виведе 'b!b'

Зверніть увагу на слєші /, в яких стоїть буква 'a'. Ці сліші називаються обмежувачами регулярних виразів.

Обмежувачі потрібні для того, щоб після них писати модифікатори. команди, які змінюють загальні властивості регулярного вираження.

Модифікатор - g - включає режим глобального пошуку і заміни - без нього регулярка шукає лише перший збіг, і з ним - все збіги. Подивіться різницю:

alert( 'aab'.replace(/a/, '!') ); //выведет '!ab'
alert( 'aab'.replace(/a/g', '!') ); //
виведе '!!b'

Є також модифікатор i - він змушує регулювання ігнорувати регістр символів:

alert( 'aAb'.replace(/A/g', '!') ); //виведе 'a!b'
alert( 'aAb'.replace(/A/gi', '!') ); //виведе '!!b'

//У другому випадку ігнорується регістр символів.

У регулярні можна вказувати кілька модифікаторів, їх порядок не має значення.

Літери, цифри, будь-який символ

У регулярних виразах є два типи символів: ті, які позначають самі себе та символи-команди (спеціальні символи).

Літери та цифри позначають самі себе, а ось точка є спеціальним символом і означає 'будь-який символ'. Дивіться приклади:

'xax xaax'.replace(/xax/g, '!'); //поверне '! xaax'
'123 xaax'.replace(/123/g, '!'); //вернет '! xaax'
'x3x xaax'.replace(/x3x/g, '!'); //вернет '! xaax'

//Зверніть увагу, що регістр має значення:
'a3b A3B'.replace(/A3B/g, '!'); //поверне 'a3b !'

Далі подивіться приклади з використанням спецсимволу 'точка':

'xax xsx x&x x-x xaax'.replace(/x.x/g, '!'); //поверне '! ! ! ! xaax'

Оскільки точка - це будь-який символ, то під наше регулювання потраплять усі підстроки за таким шаблоном: літера 'x', потім будь-який символ, потім знову літера 'x'. Перші 4 підрядки потрапили під цей шаблон (це xax xsx x&x x-x) та замінилися на '!', а останній підрядок (xaax) не потрапляє, тому що всередині (між літерами 'x') не один символ - а цілих два.

'xax xabx'.replace(/x..x/g, '!'); //поверне 'xax !'

Оскільки точка - це будь-який символ, а в нашому регулярці йдуть дві точки поспіль, то під наше регулювання потраплять усі підрядки за таким шаблоном: буква 'x', потім два будь-які символи, потім знову літера 'x'. Перший підрядок не потрапив під цей шаблон (оскільки має лише 1 символ між літерами 'x'), а останній підрядок (xabx) - потрапив.

Отже, запам'ятайте: літери та цифри позначають самі себе, а точка замінює будь-який символ.

Оператори повторення символів (*,+,?)

Бувають ситуації, коли ми хочемо вказати, що символ повторюється задану кількість разів. Якщо ми знаємо точну кількість повторень, можна просто написати його кілька разів - (/aaaa/). Але що робити, якщо ми хочемо сказати таке: 'повторити один чи більше разів'?

Для цього існують оператори (квантифікатори) повторення: плюс '+' (один і більше разів), зірочка '*' (нуль і більше разів) та питання '?' (нуль або один раз, інакше кажучи - може бути, а може не бути).

Дані оператори діють на той символ, який стоїть перед ними.

Подивіться приклади:

'xx xax xaax xaaax xbx'.replace(/xa+x/g, '!'); //поверне 'xx ! ! ! xbx'

У цьому випадку шаблон пошуку виглядає так: літера 'x', літера 'a' один або більше разів, літера 'x'.

'xx xax xaax xaaax xbx'.replace(/xa*x/g, '!'); // Поверне '! ! ! ! xbx'

В даному випадку шаблон пошуку виглядає так: літера 'x', літера 'a' нуль або більше разів, літера 'x'. Інакше можна сказати так: літери 'a' чи ні, чи повторюється один чи більше разів.

Крім очевидного варіанта xax xaax xaaax, під шаблон також потрапляє підрядок 'xx', тому що там немає букви 'a' взагалі (тобто 0 разів).

А 'xbx' не потрапив, тому що там немає букви 'a', але є буква 'b' (її ми не дозволили).

'xx xax xaax xbx'.replace(/xa?x/g, '!'); //поверне '! ! xaax xbx'

В даному випадку шаблон пошуку виглядає так: літера 'x', далі літера 'a' може бути або не бути, потім літера 'x'.

Групувальні дужки

У попередніх прикладах оператори повторення діяли лише один символ, який стояв перед ними. Що робити, якщо ми хочемо вплинути на кілька символів?

Для цього існують дужки, що групують. '(' и ')':

'xabx xababx xaabbx'.replace(/x(ab)+x/g, '!'); //поверне '! ! xaabbx'

В даному випадку шаблон пошуку виглядає так: літера 'x', далі рядок 'ab' один або більше разів, потім літера 'x'.

Тобто: якщо щось стоїть у групуючих дужках і відразу після ')' стоїть оператор повторення - він подіє на все, що стоїть усередині дужок.

Екранування спецсимволів

Припустимо, що хочемо зробити те щоб спецсимвол позначав сам себе. Наприклад, для того, щоб знайти за таким шаблоном: літера 'a', потім плюс '+', потім літера 'x'. Наступний код працюватиме не так, як хотілося б:

'a+x ax aax aaax'.replace(/a+x/g, '!'); //поверне 'a+x ! ! !''

Автор регулярки хотів, щоб шаблон пошуку виглядав так: літера 'a', потім плюс '+', потім літера 'x'.

А насправді він виглядає так: літера 'a' один або більше разів, потім літера 'x'.

Тому підрядок 'a+x' і не потрапив під шаблон (заважає '+') - а решта потрапила.

Отже, правило: щоб спецсимвол позначав сам себе - його потрібно екранувати за допомогою зворотного слішу. Ось так:

'a+x ax aax aaax'.replace(/a\+x/g, '!'); //поверне 'a+x ! ! !'

Ось тепер шаблон пошуку виглядає так, як треба: літера 'a', потім плюс '+', потім літера 'x'.

'a.x abx azx'.replace(/a\.x/g, '!'); // Поверне '! abx azx'

У цьому прикладі шаблон виглядає так: літера 'a', потім точка '.', потім літера 'x'. Порівняйте з наступним прикладом (забутий зворотний сліш):

'a.x abx azx'.replace(/a.x/g, '!'); // Поверне '! ! !'

Всі підрядки потрапили під шаблон, тому що незаекранована точка позначає будь-який символ.

Якщо ви забудете зворотний сліш для точки (коли вона повинна позначати сама себе) - цього можна навіть не помітити:

'a.x'.replace(/a.x/g, '!'); //поверне '!', як ми хотіли

Візуально працює правильно (оскільки точка позначає будь-який символ, у тому числі і звичайну точку '.'). Але якщо поміняти рядок, в якому відбуваються заміни, ми побачимо нашу помилку:

'a.x abx azx'.replace(/a.x/g, '!'); // Поверне '! ! !', А очікувалося '! abx azx'

Будьте уважні!

Список спеціальних символів та звичайних

Якщо екранувати звичайний символ - нічого страшного не станеться - він все одно позначатиме сам себе.

Часто виникає сумнів, чи цей символ є спеціальним. Деякі доходять до того, що екранують усі підозрілі символи поспіль. Однак, це погана практика (захаращує регулювання зворотними слішами).

Є спецсимволами: $ ^ . * +? \{}[]() |

Не є спецсимволами: @ : , ' '' ; - _ = < > % # ~ `&! /

Обмеження жадібності

Щоб зрозуміти, про що йтиметься - подивіться приклад:

//Виведе '! e', а чекалося '! qw x e':
'a23e4x qw x e'.replace(/a.+x/g, '!'); 

У цьому прикладі шаблон пошуку виглядає так: літера 'a', потім будь-який символ один або більше разів, потім літера 'x'.

Проте, регулярка спрацювала не так, як очікував автор - вона захопила максимально можливу кількість символів, тобто закінчилася не на першому іксі 'x', а на останньому 'x'.

Така поведінка операторів (квантифікаторів) повторення називається жадібністю - вони прагнуть забрати якнайбільше.

Така особливість не завжди корисна і, на щастя, її можна скасувати, говорячи інакше - обмежити жадібність.

Це робиться за допомогою додавання знака '?' до оператора повторення: замість жадібних '+' та '*' ми напишемо '+?' і '*?' - вони будуть не такі жадібні:

'a23e4x qw x e'.replace(/a.+?x/g, '!'); поверне '! qw x e'

У цьому прикладі шаблон пошуку виглядає так: літера 'a', потім будь-який символ один або більше разів (з обмеженням жадібності), потім літера 'x'.

За допомогою '?' ми обмежили жадібність плюсу - і тепер він шукає до першого збігу.

Жадібність можна обмежувати всім операторам повторення, у тому числі і '?', і '{}' - ось так: '??' і '{}? '.


Назад Зміст