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

Несколько символов или символьных классов в квадратных скобках […] означают «искать любой символ из заданных».

Наборы

Для примера, [eao] означает любой из 3-х символов: 'a', 'e' или 'o'.

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

// найти [t или m], а за ними "op"
alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top"

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

Так что приведённый ниже пример не даёт совпадений:

// найти "V", затем [o или i], потом "la"
alert( "Voila".match(/V[oi]la/) ); // null, нет совпадений

Шаблон предполагает:

  • V,
  • затем один из символов [oi],
  • потом la.

В этом случае совпадениями могут быть Vola или Vila.

Диапазоны

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

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

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

alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF

Обратите внимание, что в слове 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 ] плюс несколько других символов Юникода.

Ещё мы можем использовать символьные классы внутри […].

Например, мы хотим найти все символы, используемые в словах, а также тире, чтобы найти слова вида «twenty-third». Мы не можем сделать это с помощью \w+, потому что класс \w не содержит тире. Но можно использовать [\w-].

Можем использовать и несколько классов вместе, например [\s\S] означает «пробельные символы или не-пробельные символы» – то есть, вообще, любой символ. Это шире, чем точка ".", так как точка соответствует любому символу, кроме перевода строки (если не указан флаг s).

Исключающие диапазоны

Помимо обычных диапазонов, есть «исключающие» диапазоны, которые выглядят как [^…].

Они обозначаются символом каретки ^ в начале диапазона и соответствуют любому символу за исключением заданных.

Например:

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

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

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

В экранировании нет необходимости

Обычно, когда мы хотим найти именно точку, нам нужно экранировать её как \.. А если нам нужна обратная косая черта, тогда используем \\.

В квадратных скобках большинство специальных символов можно использовать без экранирования:

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

Другими словами, разрешены все специальные символы, кроме случаев, когда они означают что-то особое для диапазонов.

Точка "." внутри квадратных скобок – просто точка. Шаблон [.,] будет искать один из символов: точку или запятую.

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

// Нет необходимости в экранировании
let reg = /[-().^+]/g;

alert( "1 + 2 - 3".match(reg) ); // Совпадения +, -

…Но если вы решите экранировать «на всякий случай», то не будет никакого вреда:

// Экранирование всех возможных символов
let reg = /[\-\(\)\.\^\+]/g;

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

Задачи

У нас есть регулярое выражение /Java[^script]/.

Найдёт ли оно что-нибудь в строке Java? А в строке JavaScript?

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

  • Нет, т.к. в строке Java нет каких-либо совпадений, потому что [^script] означает «любой символ, кроме заданных». Таким образом, регулярное выражение ищет "Java", за которым следует один такой символ, но после конца строки нет символов.

    alert( "Java".match(/Java[^script]/) ); // null
  • Да, потому что регулярное выражение регистрозависимое – [^script] совпадает с символом "S".

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

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

Напишите регулярное выражение, чтобы найти время:

let reg = /your regexp/g;
alert( "Завтрак в 09:00. Ужин в 21-30".match(reg) ); // 09:00, 21-30

P.S. В этой задаче мы предполагаем, что время всегда правильное, нет необходимости отфильтровывать плохие строки, такие как «45:67». Позже мы разберёмся с этим.

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

let reg = /\d\d[-:]\d\d/g;
alert( "Завтрак в 09:00. Ужин в 21-30".match(reg) ); // 09:00, 21-30

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

Карта учебника

Комментарии

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