Синтаксис регулярных выражений

Последнее обновление: 27.10.2023

Определение классов символов

Для определения регулярных выражений мы можем использовать классы символов. Для определения класса символов применяются квадратные скобки:

  • [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

Флаг i. Регистр символов

Рассмотрим следующий пример:

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

Флаг 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
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850