Для поиска в строке более сложных соответствий применяются группы. В регулярных выражениях группы заключаются в скобки. Например, нам надо получить дату в определенном формате. С помощью метода exec() объекта RegExp мы можем получить все совпадение полностью. Допустим, дата представлена в формате "yyyy-mm-dd" (2021-09-06):
const exp = /\d{4}-\d{2}-\d{2}/; const text = "Publication Date: 2021-09-06" const result = exp.exec(text); console.log(result[0]); // 2021-09-06
Из результата метода exec мы можем извлечь результат - нужную нам дату. Однако что, если мы хотим получить отдельные компоненты дат - год, месяц, день? В этом случае мы можем воспользоваться группами.
Каждая группа представляет некоторый сегмент регулярного выражения, который заключен в круглые скобки. Например:
const exp = /(\d{4})-(\d{2})-(\d{2})/; const text = "Publication Date: 2021-09-06" const result = exp.exec(text); console.log(result); // Консольный вывод // (4) ['2021-09-06', '2021', '09', '06', index: 18, input: 'Publication Date: 2021-09-06', groups: undefined]
Здесь регулярное выражение /(\d{4})-(\d{2})-(\d{2})/
содержит три группы. Первая группа - (\d{4})
состоит из 4 цифр и представляет год.
Вторая группа - (\d{2})
состоит из 2 цифр и представляет месяц. Третья группа также состоит из 2 цифр и представляет день.
Здесь применяется регулярное выражение "/(\d{4})-(\d{2})-(\d{2})/", где определены три группы:
Первая группа (\d{4})
соответствует числу из четырех цифр
Вторая группа (\d{2})
соответствует числу из двух цифр
Третья группа аналогична второй
И если мы посмотрим на результат метода exec(), то мы увидим, что кроме собственно соответствия дате он содержит соответствия для каждой группы:
(4) ['2021-09-06', '2021', '09', '06', index: 18, input: 'Publication Date: 2021-09-06', groups: undefined]
Полученный результат представляет массив, где первый элемент (с индексом 0) всегда представляет подстроку, совпавшую с регулярным выражением. Все последующие элементы этого массива представляют группы. То есть первая группа имеет индекс 1, вторая - индекс 2 и так далее. Соответственно, применяя индексы, мы можем получить все соответствия группам из регулярного выражения:
const exp = /(\d{4})-(\d{2})-(\d{2})/; const text = "Publication Date: 2021-09-06" const result = exp.exec(text); console.log(result[0]); // 2021-09-06 - все соответствие console.log(result[1]); // 2021 - первая группа console.log(result[2]); // 09 - вторая группа console.log(result[3]); // 06 - третья группа
Получив значения отдельных групп, можно произвести с ними некоторые действия, например, преобразовать в другой формат даты:
console.log(`${result[3]}.${result[2]}.${result[1]}`); // 06.09.2021
Группировка упрощает создание более сложных регулярных выражений. К группам, как и к отдельным символам, можно применять квантификаторы. Например, выражение
(la)+
представляет одно и более повторений строки "la"&
JavaScript позволяет назначить каждой группе в регулярных выражениях определенное имя. С помощью этого имени потом можно получить значение, которое соответствует этой группе. Для установки имени групы внутри скобок, которые определяют группу, ставится знак вопроса, после которого в угловых скобках идет название группы:
(?<название_группы> ... )
Рассмотрим следующий пример:
const exp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u; const text = "Publication Date: 2021-09-06" const result = exp.exec(text); console.log(result.groups); // {year: "2021", month: "09", day: "06"} console.log(result.groups.year); // 2021 console.log(result.groups.month); // 09 console.log(result.groups.day); // 06
Здесь регулярное выражение определяет три группы. Первая группа называется "year", вторая - "month" и третья "day". При получении результата
мы можем обаться к каждой группе через свойство groups
. Это свойство представляет объект, в котором свойства называются так же, как и группы, и содержат значения для каждой группы:
console.log(result.groups); // {year: "2021", month: "09", day: "06"}
Соответственно с помощью названия группы мы можем получить значение для определенной группы.
Утверждения или assertions позвляют получить подстроку, которая соответствует регулярному выражению и которая предваряется или, наоборо, не предваряется определенным выражением.
Положительное утверждение (когда подстрока должна предваряться другой подстрокой) определяется с помощью выражения:
(?<=...)
После знака равно = идет выражение, которым должна предваряться подстрока.
Отрицательное утверждение (когда подстрока НЕ должна предваряться другой подстрокой) определяется с помощью выражения:
(?<!...)
После восклицательного знака ! идет выражение, которым НЕ должна предваряться подстрока.
Возьмем простую задачу. Допустим у нас есть некоторая информация с какой-то суммой. Но эта сумма может быть определена в долларах, в евро, в рублях и так далее. Что-то наподобие:
const text1 = "All costs: $10.53"; const text2 = "All costs: €10.53"; const exp = /\d+(\.\d*)?/; const result1 = exp.exec(text1); console.log(result1[0]); // 10.53 const result2 = exp.exec(text2); console.log(result2[0]); // 10.53
Здесь мы видим, что и сумма в долларах () и сумма в евро соответствует нашему регулярному выражению. Но что, если мы хотим получить только сумму в долларах. Для этого применим положительное утверждение:
const text1 = "All costs: $10.53"; const text2 = "All costs: €10.53"; const exp = /(?<=\$)\d+(\.\d*)?/; const result1 = exp.exec(text1); console.log(result1); // ["10.53", ".53", index: 12, input: "All costs: $10.53", groups: undefined] const result2 = exp.exec(text2); console.log(result2); // null
Группа (?<=\$)
укзывает, что перед строкой должен идти знак доллара $. Если его нет, то метод exec()
не найдет соответствий и возвратит null.