Рассмотрим практическую задачу – у нас есть номер телефона вида "+7(903)-123-45-67"
, и нам нужно превратить его в строку только из чисел: 79031234567
.
Для этого мы можем найти и удалить все, что не является числом. С этим нам помогут символьные классы.
Символьный класс – это специальное обозначение, которое соответствует любому символу из определённого набора.
Для начала давайте рассмотрим класс «цифра». Он обозначается как \d
и в регулярном выражении соответствует «любой одной цифре».
Например, давайте найдём первую цифру в номере телефона:
let str = "+7(903)-123-45-67";
let regexp = /\d/;
alert( str.match(regexp) ); // 7
Без флага g
регулярное выражение ищет только первое совпадение, то есть первую цифру \d
.
Давайте добавим флаг g
, чтобы найти все цифры:
let str = "+7(903)-123-45-67";
let regexp = /\d/g;
alert( str.match(regexp) ); // массив совпадений: 7,9,0,3,1,2,3,4,5,6,7
// и можно сделать из них уже чисто цифровой номер телефона
alert( str.match(regexp).join('') ); // 79031234567
Это был символьный класс для цифр. Есть и другие символьные классы.
Наиболее используемые:
\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
, то есть не буквы из латиницы, не знак подчёркивания и не цифра. В частности, русские буквы принадлежат этому классу.
Мы уже видели, как сделать чисто цифровой номер из строки вида +7(903)-123-45-67
: найти все цифры и соединить их.
let str = "+7(903)-123-45-67";
alert( str.match(/\d/g).join('') ); // 79031234567
Альтернативный, более короткий путь – найти нецифровые символы \D
и удалить их из строки:
let str = "+7(903)-123-45-67";
alert( str.replace(/\D/g, "") ); // 79031234567
Точка – это любой символ
Точка .
– это специальный символьный класс, который соответствует «любому символу, кроме новой строки».
Для примера:
alert( "Ю".match(/./) ); // Ю
Или в середине регулярного выражения:
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 (совпадение!)
Обычно мы уделяем мало внимания пробелам. Для нас строки 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
, который мы рассмотрим в следующей главе.