Регулярні вирази в JavaScript

Переклад 14 хв. читання

У цій статті я почну з пояснення того, що таке регулярні вирази і що вони можуть зробити для вас. Потім я представлю огляд найбільш поширених особливостей регулярних виразів. І, нарешті, я закінчу поясненням того, як регулярні вирази використовуються в JavaScript, з одним чи декількома практичними прикладами, щоб допомогти зрозуміти концепт.

Що воно таке?

Регулярні вирази використовують спеціальні (і, на перший погляд, дещо заплутані) коди для виявлення шаблонів в рядках тексту. Наприклад, якщо ви представляєте своїм відвідувачам HTML-форми для введення персональних даних, ви можете мати одне поле для номеру телефону. Тепер давайте подивимося правді в очі: деякі відвідувачі сайту краще слідують інструкціям ніж інші. Навіть якщо ви поставите підказку поруч з текстовим полем, яке вказуватиме необхідний формат телефонного номера (наприклад.: "(XXX) XXX-XXXX" для північноамериканських чисел), деякі люди все-рівно введуть дані неправильно. Написати сценарій для перевірки кожного символу введеного рядка, щоб впевнитися, що всі числа, круглі дужки і тире розміщенні в правильних місцях, було б досить складно. А номер телефону - відносно простий випадок! Що робити, якщо ви повинні були б перевірити, що користувач дійсно ввів адресу електронної пошти або, ще гірше, URL-адресу?

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

На що вони схожі?

Часом, регулярні вирази можуть виглядати досить складними, але коли доходить до справи, насправді це просто самі текстові рядки. Далі, наприклад, є регулярний вираз, який шукає текст "JavaScript" (без лапок):

JavaScript

Будь-який рядок, що містить текст "JavaScript", відповідає цьому регулярному виразу. Таким чином, регулярний вираз дозволяє нам виявити рядки, що містять конкретно цей текст. Що ж, погана новина полягає в тому, що це не завжди так просто.

Як вже згадувалося вище, існують спеціальні коди, які можуть бути використані в регулярних виразах. Деякі з них можуть бути абсолютно заплутаним і важко запам’ятовуваними, тож якщо ви маєте намір широко використовувати їх, то краще знайти гарне посилання на базу таких кодів.

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

Базовий синтаксис

Перш за все, каретка (^) використовується для позначення початку рядка, який необхідно знайти, в той час як знак долара ($) використовується для позначення кінця:

JavaScript   // Дорівнює "Isn't JavaScript great?" 
^JavaScript  // Дорівнює "JavaScript rules!", 
             //  Не дорівнює "What is JavaScript?" 
JavaScript$  // Дорівнює "I love JavaScript",
             //  Не дорівнює "JavaScript is great!" 
^JavaScript$ // Дорівнює "JavaScript", and nothing else

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

\$\$\$      // Дорівнює "Show me the $$$!"

Квадратні дужки можуть використовуватись для визначення набору символів, які можуть збігатися. Наприклад, цьому регулярному виразу будуть відповідати цифри від 1 до 5 включно.

[12345]     // Дорівнює "1" і "3", але не "a" або "12"

Можуть бути також вказані діапазони чисел і букв.

[1-5]
[a-z]
[0-9a-zA-Z]

Поставивши ^ відразу ж після відкриття квадратної дужки, ви можете інвертувати набір символів, тобто пошуку будуть відповідати будь-які не перераховані символи:

[^a-zA-Z]   // Все крім a 

Символи ?, + та * також мають особливе значення. Зокрема, ? означає "попередній символ не є обов'язковим", + означає "один або більше з попереднього символу", а * означає "нуль або більше попереднього символу".

bana?na     // Дорівнює "banana" і "banna", 
            // не дорівнює "banaana". 
bana+na     // Дорівнює "banana" і "banaana", 
            // не дорівнює "banna". 
bana*na     // Дорівнює "banna", "banana", і "banaaana", 
            // не дорівнює "bnana". 
^[a-zA-Z]+$ // Дорівнює будь-якому string з однією або більше літерами 
            // тільки літери.

Дужки можуть використовуватися для угруповання символів разом, щоб застосувати ?, + або * до них разом.

ba(na)+na   // Дорівнює "banana" і "banananana", 
            // не дорівнює "bana" або "banaana".

Дужки також дозволяють визначити кілька рядків, які можуть відповідати запиту, використовуючи вертикальну риску (|), щоб відокремити їх.

^(ba|na)+$  // Дорівнює "banana", "nababa", "baba", 
            // "nana", "ba", "na", і тд.

Ось кілька спеціальних кодів, які можуть бути використані для зіставлення символів в регулярних виразах:

.       // відповідає будь-якому символу крім розриву рядка 
\n      // відповідає символу переведення рядка
\r      // відповідає символу повернення каретки
\t      // відповідає символу горизонтальної табуляції
\b      // відповідає границі слова 
\B      // відповідає межі не-слова
\d      // теж саме, що й  [0-9] 
\D      // теж саме, що й  [^0-9] 
\s      // відповідає одного символу порожнього простору, включаючи пробіл, табуляцію, прогон сторінки, новий рядок
\S      // відповідає одиничному символу порожнього простору 
\w      // теж саме, що й [A-Za-z0-9_] 
\W      // теж саме, що й [^A-Za-z0-9_]

Зверніть увагу, що на відміну від спеціальних символів які ми розглянули раніше, деякі (наведені вище) слід використовувати зі зворотним слешем, щоб розглядатися в якості спеціальних кодів.

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

Використання регулярних виразів в JavaScript

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

var myRE = /regexp/;

Де регулярний вираз є кодом регулярним виразом, як описано вище. Наприклад, в наступному прикладі створено перший приклад регулярного виразу, який представлено в попередньому розділі, той, що визначає рядок "JavaScript":

var myRE = /JavaScript/;

Аналогічно, створюється регулярний вираз останнього прикладу:

var myRE = /^(ba|na)+$/;

За замовчуванням регулярні вирази в JavaScript чутливі до регістру і пошук відбувається тільки до першого співпадіння в будь-якому заданому рядку. Додаючи g (для глобального), і i (для ігнорування регістра) модифікатори після другого /, ви можете зробити пошук по регулярному виразу для всіх збігів в рядку і ігнорувати регістр відповідно. Ось кілька прикладів їх використання. Для кожного варіанту вказано, яка частина рядку «test1 Test2 TEST3» буде відповідати запиту:

/Test[0-9]+/ тільки “Test2”

/Test[0-9]+/i тільки “test1”

/Test[0-9]+/gi “test1”, “Test2” і “TEST3”

Використовувати регулярні вирази легко. Кожна змінна JavaScript, що містить текстовий рядок, підтримує три методи (або функції, якщо ви не звикли до об'єктно-орієнтованої термінології) для роботи з регулярними виразами: match(), replace(), і search().

match ()

match() приймає регулярний вираз як параметр і повертає масив всіх співпадаючих символів, знайдених в даному рядку. Якщо збігів не виявлено, то match() повертає значення false. Повертаючись до нашого початкового прикладу, припустимо, що нам необхідна функція, яка може перевірити, що рядок, введений користувачем як його номер телефону має вигляд (XXX) XXX-XXXX. Наступний код буде робити перевірку:

function checkPhoneNumber(phoneNo) {
  var phoneRE = /^\(\d\d\d\) \d\d\d-\d\d\d\d$/; 
  if (phoneNo.match(phoneRE)) {
    return true; 
  } else {
    alert( "Номер телефону введено невірно!" );
    return false;
  }
}

В якості першого порядку, ця функція визначає регулярний вираз. Давайте розіб’ємо його, щоб зрозуміти, як він працює. Регулярний вираз починається з ^, щоб показати, що будь-який match повинен початися на початку рядка. Далі \ (, що буде відповідати відкритій дужці. Поставивши зворотній слеш, ми видалили її особливе значення в синтаксисі регулярних виразів (позначення початку набору альтернативних для порівняння символів). Як уже згадувалося раніше, \ d є спеціальний код, який відповідає будь-якій цифрі. Таким чином, \ d \ d \ d відповідає будь-яким трьом цифрам. Ми могли б написати [0-9] [0-9] [0-9] для досягнення того ж ефекту, але перший варіант коротший. Решта коду повинна бути досить очевидною. ) відповідає за закриту дужку, і позначає місце залишене для номеру телефону, отже \ d \ d \ d- \ d \ d \ d \ d відповідає трьом цифрам, за ними слідує тире, а потім ще чотири цифри. І нарешті, $ вказує на те, що будь-який збіг має закінчуватися в кінці рядка.

Між іншим, ми могли б скоротити цей регулярний вираз, переписавши код до наступного вигляду, використовуючи можливості, про які не згадувалося вище. Якщо ви можете зрозуміти, як це працює, ви неймовірні!

var phoneRE = /^\(\d{3}\) \d{3}-\d{4}$/;

Наша функція потім перевіряє, чи phoneNo.match(phoneRE) приймає значення істина або брехня. Іншими словами, він перевіряє, відповідає чи ні рядок, що міститься в phoneNo нашому регулярному виразу (таким чином, повертаючи масив, який в JavaScript прирівнюватиметься до true). Якщо буде виявлено збіг, функція повертає true для підтвердження того, що рядок дійсно номер телефону. Якщо ні, то на дисплей виводиться повідомлення з попередженням про проблему і функція повертає false.

Найбільш поширене використання функцій такого типу, перевірка введеної користувачем інформацію до відповідної форми, перш ніж дозволити йому продовжувати роботу. Називаючи нашу функцію onSubmit обробник подій для форми, ми можемо запобігти подання неправильно заповнених інформаційних форм. Ось простий приклад, який демонструє використання нашої функції checkPhoneNumber():

<form action="...">
  <label>Enter phone number (e.g. (123) 456-7890): 
    <input type="text" name="phone">
  </label>
  <input type="submit">
</form>

<script>
  var form = document.querySelector('form');
  form.addEventListener('submit', function() {
    return checkPhoneNumber(this.phone.value);
  });
</script>

Користувач не зможе представити цю форму, якщо не буде коректно введений номер телефону. Будь-яка спроба зробити це, буде викликати повідомлення про помилку, від нашої функції checkPhoneNumber().

replace ()

Як видно з назви, replace() дозволяє замінити знайдене значення регулярного виразу деяким новим рядком. Скажімо, у вас є орфографічна помилка і ви хотіли б застосовувати стару приказку "І пишеться перед Е, але не після C" для виправлення таких помилок як "acheive" і "cieling". Нам потрібна функція, яка приймає рядок і виконує дві операції пошуку-заміни. Перша буде заміняти "CIE" з "CEI".

Ось код:

theString = theString.replace(/cie/gi,"cei");

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

Друга заміна трохи складніша. Ми хочемо, замінити "хeі" на "хіе", де "х" це будь-яка буква, крім 'с'. Регулярний вираз для виявлення варіантів "хeі" досить легко зрозуміти:

/[abd-z]ei/gi

Це просто виявляє будь-яку букву, крім 'С' ('A', 'B' і 'D' до 'Z' включно), за якою слідує "еі", і робить це глобально, без урахування регістру.

Складність приходить у визначенні нашого рядка заміни. Очевидно, що ми хочемо замінити знайдений склад на "хіе", але складність полягає в написанні 'X'. Пам'ятайте, що ми повинні замінити 'X' на таку саму букву. Для цього нам потрібно вивчити новий трюк.

Раніше, я показав вам, як круглі дужки можуть бути використані для визначення набору альтернативних значень в регулярному виразі (наприклад, ^ (ba | na) + $). Ну, як з'ясовується, круглі дужки мають і інше значення. Вони дозволяють нам "пам'ятати" частину співпадіння, так що ми можемо використовувати їх в рядку заміни. У цьому випадку, ми хочемо згадати частину збігу, яка відповідає [abd-z] в регулярному виразі. Таким чином, ми беремо її в круглі дужки:

/([abd-z])ei/gi

Тепер, при вказівці рядка заміни, ми ставимо $1, де ми хочемо вставити частину рядка, що відповідає частині регулярного виразу взятій в дужки. Отже, код для виконання необхідних замін виглядає наступним чином:

theString = theString.replace(/([abd-z])ei/gi,"$1ie");

Підводячи підсумок, ось повна функція для виконання нашої автоматичної корекції:

function autoCorrect(theString) { 
  theString = theString.replace(/cie/gi,"cei"); 
  theString = theString.replace(/([abd-z])ei/gi,"$1ie"); 
  return theString; 
}

Перед тим, як піти і використовувати цю функцію на своїй сторінці, зрозуміти, що є винятки з правила "І пишеться перед Е, але не після C". Дивно, так?

search ()

Функція search() аналогічна добре відомій функції IndexOf(), за винятком того, що їй потрібен регулярний вираз замість рядка символів. Вона здійснює пошук рядка для першого збігу по заданому регулярному виразу і повертає ціле число, яке вказує його позицію в рядку (наприклад, 0, якщо збіг знаходиться на початку рядка, 9, якщо збіг починається з 10-го символу в рядку ). Якщо збіг не знайдено, функція повертає значення -1.

var theString = "test1 Test2 TEST3";
theString.search(/Test[0-9]+/); // 6

Підводячи підсумки

Регулярні вирази є безцінним інструментом для перевірки введеної користувачем інформації. Користуючись підтримкою регулярних виразів в JavaScript, можна проводити перевірку як вводяться дані, забезпечуючи більш поступовий користувальницький досвід. (Примітка: перевірка на стороні сервера досі необхідна для забезпечення безпеки, а також ідеально підходить для ситуацій, коли JavaScript недоступний).

Джерело: Regular Expressions in JavaScript
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 6.2K
Приєднався: 7 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація