Рассмотрим практическую задачу - у нас есть номер телефона вида "+7(903)-123-45-67", и нам нужно превратить его в строку только из чисел: 79031234567.
Для этого мы можем найти и удалить всё, что не является числом. С этим нам помогут символьные классы.
Символьный класс - это специальное обозначение, которое соответствует любому символу из определённого набора.
Для начала давайте рассмотрим класс "цифра". Он обозначается как pattern:\d и в регулярном выражении соответствует "любой одной цифре".
Например, давайте найдём первую цифру в номере телефона:
let str = "+7(903)-123-45-67";
let regexp = /\d/;
alert( str.match(regexp) ); // 7Без флага pattern:g регулярное выражение ищет только первое совпадение, то есть первую цифру pattern:\d.
Давайте добавим флаг pattern: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Это был символьный класс для цифр. Есть и другие символьные классы.
Наиболее используемые:
pattern:\d ("d" от английского "digit" означает "цифра")
: Цифра: символ от 0 до 9.
pattern:\s ("s": от английского "space" – "пробел")
: Пробельные символы: включает в себя символ пробела, табуляции \t, перевода строки \n и некоторые другие редкие пробельные символы, обозначаемые как \v, \f и \r.
pattern:\w ("w": от английского "word" – "слово")
: Символ "слова", а точнее – буква латинского алфавита, цифра или подчёркивание _. Нелатинские буквы не являются частью класса pattern:\w, то есть буква русского алфавита не подходит.
Для примера, pattern:\d\s\w обозначает "цифру", за которой идёт пробельный символ, а затем символ слова, например match:1 a.
Регулярное выражение может содержать как обычные символы, так и символьные классы.
Например, pattern:CSS\d соответствует строке match: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'Соответствие (каждому символьному классу соответствует один символ результата):
Для каждого символьного класса существует "обратный класс", обозначаемый той же буквой, но в верхнем регистре.
"Обратный" означает, что он соответствует всем другим символам, например:
pattern:\D
: Не цифра: любой символ, кроме pattern:\d, например буква.
pattern:\S
: Не пробел: любой символ, кроме pattern:\s, например буква.
pattern:\W
: Любой символ, кроме pattern:\w, то есть не буква из латиницы, не знак подчёркивания и не цифра. В частности, русские буквы принадлежат этому классу.
Мы уже видели, как сделать чисто цифровой номер из строки вида subject:+7(903)-123-45-67: найти все цифры и соединить их.
let str = "+7(903)-123-45-67";
alert( str.match(/\d/g).join('') ); // 79031234567Альтернативный, более короткий путь - найти нецифровые символы pattern:\D и удалить их из строки:
let str = "+7(903)-123-45-67";
alert( str.replace(/\D/g, "") ); // 79031234567Точка pattern:. - это специальный символьный класс, который соответствует "любому символу, кроме новой строки".
Для примера:
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, нет совпадений, потому что нет символа для точкиОбычно точка не соответствует символу новой строки \n.
То есть регулярное выражение pattern:A.B будет искать символ match:A и затем match:B, с любым символом между ними, кроме перевода строки \n:
alert( "A\nB".match(/A.B/) ); // null (нет совпадения)Но во многих ситуациях точкой мы хотим обозначить действительно "любой символ", включая перевод строки.
Как раз для этого нужен флаг pattern:s. Если регулярное выражение имеет его, то точка pattern:. соответствует буквально любому символу:
alert( "A\nB".match(/A.B/s) ); // A\nB (совпадение!)Обычно мы уделяем мало внимания пробелам. Для нас строки `subject:1-5` и `subject: 1 - 5` практически идентичны.
Но если регулярное выражение не учитывает пробелы, оно может не сработать.
Давайте попробуем найти цифры, разделённые дефисом:
```js run
alert( "1 - 5".match(/\d-\d/) ); // null, нет совпадения!
```
Исправим это, добавив пробелы в регулярное выражение `pattern:\d - \d`:
```js run
alert( "1 - 5".match(/\d - \d/) ); // 1 - 5, теперь работает
// или можно использовать класс \s:
alert( "1 - 5".match(/\d\s-\s\d/) ); // 1 - 5, тоже работает
```
**Пробел - это символ. Такой же важный, как любой другой.**
Нельзя просто добавить или удалить пробелы из регулярного выражения, и ожидать, что оно будет работать так же.
Другими словами, в регулярном выражении все символы имеют значение, даже пробелы.
Существуют следующие символьные классы:
pattern:\d-- цифры.pattern:\D-- не цифры.pattern:\s-- пробельные символы, табы, новые строки.pattern:\S-- все, кромеpattern:\s.pattern:\w-- латиница, цифры, подчёркивание_.pattern:\W-- все, кромеpattern:\w.pattern:.-- любой символ, если с флагом регулярного выраженияpattern:s, в противном случае любой символ, кроме перевода строки\n.
...Но это не всё!
В кодировке Юникод, которую JavaScript использует для строк, каждому символу соответствует ряд свойств, например - какого языка это буква (если буква), является ли символ знаком пунктуации, и т.п.
Можно искать, в том числе, и по этим свойствам. Для этого нужен флаг pattern:u, который мы рассмотрим в следующей главе.