Наборы и диапазоны [...]

Если в регулярном выражении несколько символов или символьных классов заключены в квадратные скобки […], то это означает "искать любой символ из указанных в […]".

Набор

Например, [еао] означает любой символ из этих трёх: 'а', 'е', или 'о'.

Такое обозначение называют набором. Наборы используются в регулярном выражении наравне с обычными символами:

// найти [г или т], а затем "оп"
alert( "Гоп-стоп".match(/[гт]оп/gi) ); // "Гоп", "топ"

Обратим внимание: несмотря на то, что в наборе указано несколько символов, в совпадении должен присутствовать ровно один из них.

Поэтому в примере ниже нет результатов:

// найти "В", затем [у или а], затем "ля"
alert( "Вуаля".match(/В[уа]ля/) ); // совпадений нет

Поиск подразумевает:

  • В,
  • затем одну из букв набора [уа],
  • а затем ля

Таким образом, совпадение было бы для строки Вуля или Валя.

Диапазоны

Квадратные скобки могут также содержать диапазоны символов.

Например, [a-z] – произвольный символ от a до z, [0-5] – цифра от 0 до 5.

В примере ниже мы будем искать "x", после которого идёт два раза любая цифра или буква от A до F:

// найдёт "xAF"
alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) );

Обратим внимание, в слове Exception есть сочетание xce, но оно не подошло, потому что буквы в нём маленькие, а в диапазоне [0-9A-F] – большие.

Если хочется искать и его тоже, можно добавить в скобки диапазон a-f: [0-9A-Fa-f]. Или же просто указать у всего регулярного выражения флаг i.

Символьные классы – всего лишь более короткие записи для диапазонов, в частности:

  • \d – то же самое, что [0-9],
  • \w – то же самое, что [a-zA-Z0-9_],
  • \s – то же самое, что [\t\n\v\f\r ] плюс несколько юникодных пробельных символов.

В квадратных скобках можно использовать и диапазоны и символьные классы – вместе.

Например, нам нужно найти все слова в тексте. Если они на английском – это достаточно просто:

var str = "The sun is rising!";

alert( str.match(/\w+/g) ); // The, sun, is, rising

В этом примере мы забежали немного вперёд и использовали pattern\w+, что означает один или более символов, подходящих под классpattern\w. Позже мы рассмотрим + детальнее, а пока – давайте посмотрим, найдутся ли слова на русском?

var str = "Солнце встаёт!";

alert( str.match(/\w+/g) ); // null

Ничего не найдено! Это можно понять, ведь \w – это именно английская букво-цифра, как можно видеть из аналога [a-zA-Z0-9_].

Чтобы находило слово на русском – нужно использовать диапазон, например /[а-я]/.

А чтобы на обоих языках – и то и другое вместе:

var str = "Солнце (the sun) встаёт!";

alert( str.match(/[\wа-я]+/gi) ); // Солнце, the, sun, вста, т

…Присмотритесь внимательно к предыдущему примеру! Вы видите странность? Оно не находит букву ё, более того – считает её разрывом в слове. Причина – в кодировке юникод, она подробно раскрыта в главе Строки.

Буква ё лежит в стороне от основной кириллицы и её следует добавить в диапазон дополнительно, вот так:

var str = "Солнце (the sun) встаёт!";

alert( str.match(/[\wа-яё]+/gi) ); // Солнце, the, sun, встаёт

Теперь всё в порядке.

Диапазоны «кроме»

Кроме обычных, существуют также исключающие диапазоны: [^…].

Квадратные скобки, начинающиеся со знака каретки: [^…] находят любой символ, кроме указанных.

Например:

  • [^аеуо] – любой символ, кроме 'a', 'e', 'y', 'o'.
  • [^0-9] – любой символ, кроме цифры, то же что \D.
  • [^\s] – любой не-пробельный символ, то же что \S.

Пример ниже ищет любые символы, кроме букв, цифр и пробелов:

alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // "@", "."

Не нужно экранирование

Обычно, если мы хотим искать именно точку, а не любой символ, или именно символ \, то мы используем экранирование: указываем \. или \\.

В квадратных скобках большинство специальных символов можно использовать без экранирования, если конечно они не имеют какой-то особый смысл именно внутри квадратных скобок.

То есть, «как есть», без экранирования можно использовать символы:

  • Точка '.'.
  • Плюс '+'.
  • Круглые скобки '( )'.
  • Дефис '-', если он находится в начале или конце квадратных скобок, то есть не выделяет диапазон.
  • Символ каретки '^', если не находится в начале квадратных скобок.
  • А также открывающая квадратная скобка '['.

То есть, точка "." в квадратных скобках означает не «любой символ», а обычную точку.

Регэксп [.,] ищет один из символов «точка» или «запятая».

В примере ниже регэксп [-().^+] ищет один из символов -().^. Они не экранированы:

// Без экранирования
var re = /[-().^+]/g;

alert( "1 + 2 - 3".match(re) ); // найдёт +, -

…Впрочем, даже если вы решите «на всякий случай» заэкранировать эти символы, поставив перед ними обратный слэш \ – вреда не будет:

// Всё заэкранировали
var re = /[\-\(\)\.\^\+]/g;

alert( "1 + 2 - 3".match(re) ); // тоже работает: +, -

Задачи

Ответы: нет, да.

  • В строке Java он ничего не найдёт, так как исключающие квадратные скобки в Java[^...] означают «один символ, кроме указанных». А после «Java» – конец строки, символов больше нет.

    alert( "Java".match(/Java[^script]/) ); // нет совпадений
  • Да, найдёт. Поскольку регэксп регистрозависим, то под [^script] вполне подходит символ "S".

    alert( "JavaScript".match(/Java[^script]/) ); // "JavaS"

Найдет ли регэксп /Java[^script]/ что-нибудь в строке Java?

А в строке JavaScript?

Ответ: \d\d[-:]\d\d.

var re = /\d\d[-:]\d\d/g;
alert( "Завтрак в 09:00. Обед - в 21-30".match(re) );

Обратим внимание, что дефис '-' не экранирован, поскольку в начале скобок он не может иметь специального смысла.

Время может быть в формате часы:минуты или часы-минуты. И часы и минуты состоят из двух цифр, например 09:00, 21-30.

Напишите регулярное выражение для поиска времени:

var re = /ваше выражение/;
alert( "Завтрак в 09:00. Обед - в 21-30".match(re) ); // 09:00, 21-30
Карта учебника

Комментарии

перед тем как писать…
  • Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.