Розглянемо практичне завдання – у нас є номер телефону типу "+1(703)-123-45-67"
, і нам потрібно перетворити його на рядок тільки з чисел: 17031234567
.
Для цього ми можемо знайти та видалити все, що не є числом. Із цим нам допоможуть символьні класи.
Символьний клас – це спеціальне позначення, яке відповідає будь-якому символу з певного набору.
Для початку давайте розглянемо клас “цифра”. Він позначається як \d
і відповідає “будь-якій одній цифрі”.
Наприклад, знайдемо першу цифру в номері телефону:
let str = "+1(703)-123-45-67";
let regexp = /\d/;
alert( str.match(regexp) ); // 1
Без прапора g
регулярний вираз шукає лише перший збіг, тобто першу цифру \d
.
Давайте додамо прапор g
, щоб знайти всі цифри:
let str = "+1(703)-123-45-67";
let regexp = /\d/g;
alert( str.match(regexp) ); // масив збігів: 1,7,0,3,1,2,3,4,5,6,7
// давайте зробимо з них номер телефону лише з цифр:
alert( str.match(regexp).join('') ); // 17031234567
Це був символьний клас для цифр. Є й інші символьні класи.
Найбільш використовувані:
\d
(“d” від англійского “digit” означає “цифра”)- Цифра: символ від
0
до9
. \s
(“s” від англійского “space” означає “пробіл”)- Пробільні символи: включає символ пробілу, табуляції
\t
, перенесення рядка\n
і деякі інші рідкісні пробілові символи, що позначаються як\v
,\f
і\r
. \w
(“w” від англійского “word” означає “слово”)- Символ “слова” – літера латинського алфавіту, цифра або символ підкреслення
_
. Нелатинські літери (наприклад, кирилиця чи хінді) не належать до\w
.
Наприклад, \d\s\w
означає “цифру”, за якою йде “символ пробілу”, після якого йде “символ слова”, наприклад 1 a
.
Регулярний вираз може містити як звичайні символи, так і символьні класи.
Наприклад, CSS\d
відповідає рядку CSS
із цифрою після нього:
let str = "Чи існує CSS4?";
let regexp = /CSS\d/
alert( str.match(regexp) ); // CSS4
Також ми можемо використовувати багато символьних класів:
alert( "I love HTML5!".match(/\s\w\w\w\w\d/) ); // ' HTML5'
Відповідність (кожному символьному класу відповідає один символ результату):
Зворотні символьні класи
Для кожного символьного класу існує “зворотній клас”, що позначається тією ж літерою, але у верхньому регістрі.
“Зворотній” означає, що він відповідає всім іншим символам, наприклад:
\D
- Не цифра: будь-який символ, окрім
\d
, наприклад, літера. \S
- Не пробіл: будь-який символ, окрім
\s
, наприклад, літера. \W
- Будь-який символ, окрім
\w
, тобто не букви з латиниці, не символ підкреслення і цифра.
На початку розділу ми бачили, як створити номер телефону з рядка виду +1(703)-123-45-67
: знайти всі цифри та з’єднати їх.
let str = "+1(703)-123-45-67";
alert( str.match(/\d/g).join('') ); // 17031234567
Альтернативний, коротший шлях – знайти нецифрові символи \D
і видалити їх з рядка:
let str = "+1(703)-123-45-67";
alert( str.replace(/\D/g, "") ); // 17031234567
Крапка – це будь-який символ
Крапка .
– це спеціальний символьний клас, який відповідає “будь-якому символу, крім символу нового рядка”.
Наприклад:
alert( "Y".match(/./) ); // Y
Або в середині регулярного виразу:
let regexp = /CS.4/;
alert( "CSS4".match(regexp) ); // CSS4
alert( "CS-4".match(regexp) ); // CS-4
alert( "CS 4".match(regexp) ); // CS 4 (пробіл також є символом)
Зверніть увагу, що точка означає “будь-який символ”, але не “відсутність символу”. Там має бути будь-який символ, щоб відповідати умові пошуку:
alert( "CS4".match(/CS.4/) ); // null, немає збігів тому що немає символу для точки
Крапка, як буквально будь-який символ із прапорцем “s”.
За замовчуванням крапка не відповідає символу нового рядка \n
.
Наприклад, регулярний вираз A.B
відповідає A
, а потім B
з будь-яким символом між ними, крім символу нового рядка \n
:
alert( "A\nB".match(/A.B/) ); // null (немає збігів)
Є багато ситуацій, коли ми хотіли б, щоб крапка означала буквально “будь-який символ”, включаючи новий рядок.
Ось що робить прапор s
. Якщо регулярний вираз містить його, то крапка .
відповідає буквально будь-якому символу:
alert( "A\nB".match(/A.B/s) ); // A\nB (збіг!)
Прапор s
не підтримується в IE.
На щастя, є альтернатива, яка працює всюди. Ми можемо використовувати регулярний вираз, як-от [\s\S]
, щоб знаходити “будь-який символ” (цей шаблон буде описано в статті Набори та діапазони [...]).
alert( "A\nB".match(/A[\s\S]B/) ); // A\nB (збіг!)
Шаблон [\s\S]
буквально говорить: “пробіл АБО не пробіл”. Іншими словами, “що завгодно”. Ми могли б використати іншу пару додаткових класів, наприклад [\d\D]
, це не має значення. Або навіть [^]
– оскільки це означає збіг будь-якого символу, крім нічого.
Також ми можемо використати цей прийом, якщо хочемо, щоб обидва типи “крапок” були в одному шаблоні: наявний шаблон .
крапки, який поводиться звичайним чином (“без нового рядка”), а також відповідності “будь-якому символу” з [\s\S]
або подібним.
Зазвичай ми приділяємо мало уваги пробілам. Для нас рядки 1-5
і 1 - 5
майже ідентичні.
Але якщо регулярний вираз не враховує пробіли, він може не спрацювати.
Спробуємо знайти цифри, розділені дефісом:
alert( "1 - 5".match(/\d-\d/) ); // null, немає збігів!
Давайте виправимо це, додавши пробіли в регулярний вираз \d - \d
:
alert( "1 - 5".match(/\d - \d/) ); // 1 - 5, тепер працює
// або ми можемо використати \s клас:
alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, також працює
Пробіл – це символ. Так само важливий, як і будь-який інший.
Ми не можемо додавати або видаляти пробіли в регулярному виразі й сподіватися, що він працюватиме так само.
Іншими словами, у регулярному виразі всі символи мають значення, пробіли також.
Підсумки
Існують такі класи символів:
\d
– цифри.\D
– нецифри.\s
– символи пробілів, табуляції, символи нового рядка.\S
– усі, крім\s
.\w
– латинські літери, цифри, підкреслення'_'
.\W
– усі, крім\w
..
– будь-який символ, якщо з прапорцем регулярного виразу's'
, інакше будь-який, крім символу нового рядка\n
.
…Але це ще не все!
Кодування Юнікод, яке використовується JavaScript для рядків, надає багато властивостей для символів, наприклад: до якої мови належить літера (якщо це літера), чи це знак пунктуації тощо.
Ми також можемо шукати за цими властивостями. Для цього потрібен прапорець u
, який описано в наступній статті.