Як ми бачили, бекслеш \ використовується для позначення класів символів, напр. \d. Це спеціальний символ у регулярних виразах (як і у звичайних рядках).
Існують також інші спеціальні символи, які мають особливе значення в регулярних виразах, наприклад [ ] { } ( ) \ ^ $ . | ? * +. Вони використовуються, щоб посилити можливості пошуку.
Не намагайтеся запам’ятати список – незабаром ми розберемо кожен з них окремо, і ви їх легко запам’ятаєте.
Екранування
Скажімо, ми хочемо знайти саме крапку. Не “будь-який символ”, а просто крапку.
Щоб використовувати спеціальний символ як звичайний, додайте перед ним бекслеш: \..
Це називається “екранування символу”.
Наприклад:
alert( "Chapter 5.1".match(/\d\.\d/) ); // 5.1 (співпадіння!)
alert( "Chapter 511".match(/\d\.\d/) ); // null (шукаємо справжню крапку \.)
Дужки також є спеціальними символами, тому, якщо нам потрібно їх знайти, ми повинні використовувати \(. У прикладі нижче шукаємо рядок "g()":
alert( "function g()".match(/g\(\)/) ); // "g()"
Якщо ми шукаємо бекслеш \, як ви пам’ятаєте, це спеціальний символ як у звичайних рядках, так і в регулярних виразах, ми повинні подвоїти його (екранувати).
alert( "1\\2".match(/\\/) ); // '\'
Слеш
Символ слешу '/' не є спеціальним символом, але в JavaScript він використовується для відкриття та закриття регулярного виразу: /...pattern.../, тому ми також повинні екранувати його.
Ось як виглядає пошук слешу '/':
alert( "/".match(/\//) ); // '/'
З іншого боку, якщо ми не використовуємо /.../, а створюємо регулярний вираз за допомогою new RegExp, тоді нам не потрібно його екранувати:
alert( "/".match(new RegExp("/")) ); // знаходить /
new RegExp
Якщо ми створюємо регулярний вираз за допомогою new RegExp, тоді нам не потрібно екранувати /, але потрібно зробити інше екранування.
Наприклад, розглянемо наступний код:
let regexp = new RegExp("\d\.\d");
alert( "Chapter 5.1".match(regexp) ); // null
Подібний пошук в одному з попередніх прикладів працював із /\d\.\d/, але new RegExp("\d\.\d") не працює, чому?
Причина полягає в тому, що рядок “поглинає” бекслеши. Як ми можемо пам’ятати, звичайні рядки мають власні спеціальні символи, такі як \n, а бекслеш використовується для їх екранування.
Ось як сприймається “\d.\d”:
alert("\d\.\d"); // d.d
Рядкові лапки “поглинають” зворотні слеши та інтерпретують їх самостійно, наприклад:
\n– стає символом нового рядка,\u1234– стає символом Unicode з таким кодом,- …А коли немає особливого значення: як-от
\dабо\z, тоді бекслеш просто видаляється.
Тому new RegExp отримує рядок без бекслешів, і пошук не працює!
Щоб це виправити, нам потрібно подвоїти бекслеши, оскільки лапки рядка автоматично перетворюють \\ на \:
let regStr = "\\d\\.\\d";
alert(regStr); // \d\.\d (тепер правильно)
let regexp = new RegExp(regStr);
alert( "Chapter 5.1".match(regexp) ); // 5.1
Підсумки
- Для пошуку спеціальних символів
[ \ ^ $ . | ? * + ( ), нам потрібно додати перед ними\(“екранувати їх”). - Нам також потрібно екранувати
/, якщо ми знаходимося всередині/.../(але не всерединіnew RegExp). - При передачі рядка в
new RegExp, нам необхідно подвоїти бекслеши\\, бо лапки рядка поглинають один з них.
Коментарі
<code>, для кількох рядків – обгорніть їх тегом<pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)