Для определения регулярных выражений мы можем использовать классы символов. Для определения класса символов применяются квадратные скобки:
[xyz] (альтернативное соответствие): соответствует одному из символов: x, y или z (аналог x|y|z
)
[^xyz] (отрицание): соответствует тексту, который содержит любые символы КРОМЕ x, y или z
[a-zA-Z] (диапазон): соответствует любому символу из диапазона a-z или A-Z
Например, нам надо проверить, есть ли в тексте символы "a", "b" или "c":
const exp = /[abc]/; // соответствует либо "a", либо "b", либо "c" const str1 = "JavaScript"; const str2 = "Pascal"; const str3 = "Python"; console.log(exp.test(str1)); // true console.log(exp.test(str2)); // true console.log(exp.test(str3)); // false
Выражение [abc]
указывает на то, что строка должна иметь одну из трех букв. Выражение "[abc]" также эквивалентно выражению "a|b|c".
Возьмем более практический пример. Допустим, у нас есть 4-х символьные pin-коды, и нам надо проверить, что pin-код содержит только цифры:
const exp = /[0-9][0-9][0-9][0-9]/; // соответствует четырем цифрам подряд const code1 = "1234"; const code2 = "jav5"; const code3 = "3452"; console.log(exp.test(code1)); // true console.log(exp.test(code2)); // false console.log(exp.test(code3)); // true
Выражение [0-9][0-9][0-9][0-9]
соответствует любой последовательности из 4 цифр подряд. Например, такому шаблону соответствует строка "3452", но НЕ
соответствует строка "jav5" (здесь только одна цифра). Строка "jav5" соответстветствовала бы шаблону "[a-z][a-z][a-z][0-9]" (первые три алфафитных символа в нижнем регистре, за которыми идет цифра).
Сразу стоит отметить, что выражение [0-9][0-9][0-9][0-9]
не оптимально, и далее мы посмотрим, как его можно упростить.
Еще один пример - применим отрицание:
const exp = /[^a-z]/; // соответствует любым символам, кроме символов из диапазона a-z const code1 = "zorro"; const code2 = "zorro5"; const code3 = "34521"; console.log(exp.test(code1)); // false console.log(exp.test(code2)); // true console.log(exp.test(code3)); // true
Здесь строки проверяются на соответствие выражению "[^a-z]", которое соответствует любым символам, кроме символов из диапазона a-z. Например, строка "zorro" НЕ соответствует этому выражению. Однако ему соответствует строка "zorro5", потому что в ней есть символ, не входящий в диапазон "a-z".
При необходимости мы можем собирать комбинации выражений:
const exp = /[дт]о[нм]/; // соответствует строкам "дом", "том", "дон", "тон" const str1 = "дома"; const str2 = "сома"; const str3 = "тона"; console.log(exp.test(str1)); // true console.log(exp.test(str2)); // false console.log(exp.test(str3)); // true
Выражение [дт]о[нм]
указывает на те строки, которые могут содержать подстроки "дом", "том", "дон", "тон".
Вместо определения своих классов символов мы можем использовать встроенные, которые еще называют метасимволы - символы, которые имеют определенный смысл:
\d
: соответствует любой цифре от 0 до 9. Аналогичен выражению [0-9]
\D
: соответствует любому символу, который не является цифрой. Аналогичен выражению [^0-9]
\w
: соответствует любой букве, цифре или символу подчеркивания (диапазоны A–Z, a–z, 0–9). Аналогичен выражению [a-zA-Z_0-9]
\W
: соответствует любому символу, который не является буквой, цифрой или символом подчеркивания (то есть не находится
в следующих диапазонах A–Z, a–z, 0–9). Аналогичен выражению [^\w]
\s
: соответствует пробелу. Аналогичен выражению [\t\n\x0B\f\r]
\S
: соответствует любому символу, который не является пробелом. Аналогичен выражению [^\s]
.
: соответствует любому символу
Здесь надо заметить, что метасимвол \w применяется только для букв латинского алфавита, кириллические символы для него не подходят.
Так, выше для проверки, что код имеет только 4 цифры, использовалось выражение /[0-9][0-9][0-9][0-9]/
. Мы его можем сократить, используя метасимвол "\d":
const exp = /\d\d\d\d/; // соответствует четырем цифрам подряд const code1 = "1234"; const code2 = "jav5"; const code3 = "3452"; console.log(exp.test(code1)); // true console.log(exp.test(code2)); // false console.log(exp.test(code3)); // true
Другой пример. Допустим, нам надо найти строки, где определен номер телефона. Причем, номер телефона в формате +х-ххх-ххх-хххх:
const exp = /\+\d-\d\d\d-\d\d\d-\d\d\d\d/; const contact1 = "Email: mycomp@gmail.com"; const contact2 = "Phone: +1-234-567-8901"; console.log(exp.test(contact1)); // false console.log(exp.test(contact2)); // true
Так, номеру телефона +1-234-567-8901 соответствует /\+\d-\d\d\d-\d\d\d-\d\d\d\d/
:
\+ | \d | - | \d | \d | \d | - | \d | \d | \d | - | \d | \d | \d | \d |
+ | 1 | - | 2 | 3 | 4 | - | 5 | 6 | 7 | - | 8 | 9 | 0 | 2 |
Обратите внимание на слеш перед плюсом (\+). Поскольку плюс + имеет специальное значение, то, чтобы указать, что мы имеет ввиду именно плюс как символ строки, перед ним ставится слеш.
В результате в строке "Phone: +1-234-567-8901" метод exp.test(contact2)
сопоставит с регулярным выражением подстроку "+1-234-567-8901"
Ряд специальных символов позволяют ограничить диапазон применения регулярных выражений:
^: соответствует началу строки. Например, ^h
соответствует строке "home", но не "ohma", так как h должен представлять начало строки
$: соответствует концу строки. Например, м$
соответствует строке "дом", так как строка должна оканчиваться на букву м
\b: соответствует началу или концу слова.
\B: не учитывает границы слова
Например, нам нужно найти строки с номером телефона:
const exp = /\d\d\d\d\d\d\d\d\d\d/; // соответствует 10 цифрам подряд const phone1 = "+12345678901"; const phone2 = "42345678901"; console.log(exp.test(phone1)); // true console.log(exp.test(phone2)); // true
Шаблону /\d\d\d\d\d\d\d\d\d\d/
соответствуют как строка "+12345678901", так и строка "42345678901". Но, допустим, нам надо найти номера телефонов,
которые не предваряются плюсом +. В этом случае мы можем использовать регулярное выражение /^\d\d\d\d\d\d\d\d\d\d/
. Таким образом, строка будет соответствовать шаблону,
если она начинается с цифровых символов:
const exp = /^\d\d\d\d\d\d\d\d\d\d/; // соответствует 10 цифрам подряд const phone1 = "+12345678901"; const phone2 = "42345678901"; console.log(exp.test(phone1)); // false console.log(exp.test(phone2)); // true
Другой пример. Пусть нам надо проверить, есть ли в строке упонимание языка "Java". Наивный подход состоял бы в использовании регулярного выражения /Java/
:
const exp = /Java/; const str1 = "Java is a high-level, object-oriented programming language"; const str2 = "JavaScript is a programming language of the World Wide Web"; console.log(exp.test(str1)); // true console.log(exp.test(str2)); // true
Однако в реальности шаблон "/Java/" соответствует любой строке, которая содержит подстроку "Java", в том числе строке "JavaScript". Однако нам надо найти только те строки, где речь идет именно о Java, а не о JavaScript. И в этом случае мы можем ограничить поиск границами слова с помощью "\b":
const exp = /Java\b/; // const str1 = "Java is a high-level, object-oriented programming language"; const str2 = "JavaScript is a programming language of the World Wide Web"; console.log(exp.test(str1)); // true console.log(exp.test(str2)); // false
Флаг "\B", наоборот, указывать сопоставлять шаблон с подстроками, которые не являются слова:
const exp = /Java\B/; // const str1 = "Java is a high-level, object-oriented programming language"; const str2 = "JavaScript is a programming language of the World Wide Web"; console.log(exp.test(str1)); // false console.log(exp.test(str2)); // true
Флаги позволяют настроить поведение регулярных выражений. Каждый флаг представляет отдельный символ, который ставится в конце регулярного выражения. В JavaScript применяются следующие флаги:
Флаг global позволяет найти все подстроки, которые соответствуют регулярному выражению. По умолчанию при поиске подстрок регулярное выражение выбирает первую попавшуюся подстроку из строки, которая соответствует выражению. Хотя в строке может быть множество подстрок, которые также соответствуют выражению. Для этого применяется данный флаг в виде символа g в выражениях
Флаг ignoreCase позволяет найти подстоки, которые соответствуют регулярному выражению, вне зависимости от регистра символов в строке. Для этого в регулярных выражениях применяется символ i
Флаг multiline позволяет найти подстроки, которые соответствуют регулярному выражению, в многострочном тексте. Для этого в регулярных выражениях применяется символ m
Флаг dotAll позволяет сопоставить точку в регулярном выражении с любым символом текста, в том числе с разделителем строки. Для этого в регулярных выражениях применяется символ s
Рассмотрим следующий пример:
const str = "Hello World"; const exp = /world/; console.log(exp.test(str)); // false
Здесь совпадения строки с выражением нет, так как "World" отличается от "world" по регистру. В этом случае надо изменить регулярное выражение, добавив в него флаг i:
const str = "Hello World"; const exp = /world/i; console.log(exp.test(str)); // true
Обратите внимание, где в регулярном выражении указывается флаг: /world/i
- в самом конце регулярного выражения.
Флаг s позволяет сопоставить символ . (точка) с любым символом, в том числе и с разделителем строки. Например, возьмем следующий пример:
const str = "hello\nworld"; const exp = /hello world/; console.log(exp.test(str)); // false
Здесь в строке "hello\nworld" слова "hello" и "world" разделены переносом строки (например, мы имеем дело с многострочным текстом). Однако, например,
мы хотим, чтобы JavaScript не учитывал перенос строки и чтобы данный текст соответствовал регулярному выражению /hello world/
. В этом случае мы можем применить
флаг s:
const str = "hello\nworld"; const exp = /hello.world/s; console.log(exp.test(str)); // true
В выражении /hello.world/s
точка означает произвольный символ. Однако без флага s данное выражение не будет
соответствовать многострочному тексту.
Также можно использовать сразу несколько флагов:
const str = "hello\nWorld"; const exp = /hello.world/si; console.log(exp.test(str)); // true