12 жовтня 2022 р.

Символьні класи

Розглянемо практичне завдання – у нас є номер телефону типу "+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 (збіг!)
Не підтримується в IE

Прапор 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, який описано в наступній статті.

Навчальна карта