SRE : Группы

Регулярные выражения : Группы



Группы это части шаблона заключённые в круглые скобки. С помощью групп можно сформировать возвращающий массив, объединить элементы выбора (?:_|_), создать ссылки на группы.


С помощью групп можно сформировать возвращающий массив

#include <Array.au3>
$sText = '<i>Высота</i> <b>15</b> <i>Ширина</i> <b>22</b>'
$sPattern = '<i>(.*?)</i> <b>(.*?)</b> <i>(.*?)</i> <b>(.*?)</b>'
$aRes = StringRegExp($sText, $sPattern, 1)
_ArrayDisplay($aRes, 'aRes')


С помощью группы можно объединить несколько допустимых вариантов. Выбор одного из элементов группы с использованием метасимвола ИЛИ.

If StringRegExp('HKCU', 'HK(LM|U|CU|CR|CC)') Then
    MsgBox(0, 'Сообщение', 'Да это корневой раздел реестра')
EndIf


Пример на основе ссылок на группы

#include <Array.au3>
$sText = 'ВВысота, ШШирррина'
$sPattern = '([А-яЁё])\1+'
$sText = StringRegExpReplace($sText, $sPattern, '\1')
MsgBox(0, 'Сообщение', $sText)


Как определить номер ссылки на группу? Счёт идёт слева направо, по очерёдности открывающей скобки. Допустимы любые варианты с многократным вложением ((\d)((\d)\d))(\d). В данном примере группы только формируют возвращаемый массив. Вы даже можете удалить все скобки оставив \d\d\d\d, это не изменит шаблон, он также будет найден, только возвращается уже как одна группа. Экспериментируйте с перестановкой скобок и посмотрите возвращаемый массив.

#include <Array.au3>
$aRes = StringRegExp('1234', '((\d)((\d)\d))(\d)', 1)
_ArrayDisplay($aRes)


Если группа используется для перечисления вариантов с метасимволом ИЛИ, а также в других случаях, когда не требуется вывод группы в результат, то используйте конструкцию (?:текст), чтобы исключить группу из сохраняемых. При этом группа не будет иметь ссылки, не будет возвращаться в массив и это экономит память.

#include <Array.au3>
$aRes = StringRegExp('HKCU,HKLM', 'HK(?:LM|U|CU|CR|CC)', 2)
_ArrayDisplay($aRes)


С помощью групп можно поменять местами элементы поиска. Пример с анаграммой.

$sText = 'банка'
$aRes = StringRegExpReplace($sText, '(...)(..)', '\2\1')
MsgBox(0, $sText, $aRes)


В чём отличие групп (?:...) и (?=...), которые можно использовать в качестве неиспользуемой группы как продолжение шаблона на более точное соответствие? Первый вариант кажется более универсальным и его можно применить как справа так и слева. Но существует важное отличие: конец поиска, после которого следует начать поиск следующего совпадения у (?:...) заканчивается в конце этой группы, а у (?=...) в начале этой группы.

Шаблон (дубль_)(?:дубль) будет захватывать по 2 дубля.
дубль_дубль_дубль_дубль_дубль_

Шаблон (дубль_)(?=дубль) будет захватывать по 1-му дублю, далее просто проверяется, что найденное заканчивается текстом "дубль".
дубль_дубль_дубль_дубль_дубль_
Группа (?!...) имеет такое же свойство при поиске, только проверяет не совпадение.

#include <Array.au3>
$sText = 'дубль_дубль_дубль_дубль_дубль_'
$aRes = StringRegExp($sText, '(дубль_)(?:дубль_)', 3)
_ArrayDisplay($aRes, '(?:...)') ; возвращает 2 элемента
$aRes = StringRegExp($sText, '(дубль_)(?=дубль_)', 3)
_ArrayDisplay($aRes, '(?=...)') ; возвращает 4 элемента



К группе как отдельно взятому элементу можно применять метасимволы повтора, такие как +, *, ?, {3}
В ниже приведённом примере к тексту "www." применена конструкция (?:www\.)? это означает, что текст группы может существовать или не существовать. При использовании StringRegExp произойдёт возвращение группы, даже если она не существует, просто будет пустой элемент массива. Поэтому такая группа должна быть исключена из возвращаемого массива конструкцией (?:...)

$sText = 'http://www.autoitscript.com'
$aRes=StringRegExpReplace($sText, 'http://(?:www\.)?(.*)', '\1')
MsgBox(0, 'Сообщение', $aRes)