Непоследовательные и необязательные группы захвата
Каким образом в регулярных выражениях определяются необязательные и, что более важнее, непоследовательные группы захвата?
Объясню на примере. Предположим, что у нас есть некоторые строки, например из log-файла, которые обрабатываются с помощью регулярных выражений:
01.01.2021 - 00:00:00 TRACE part is created
01.01.2021 - 00:00:00 TRACE part.id=42
01.01.2021 - 01:10:11 TRACE part.id=11, order.id=1
02.02.2022 - 02:20:22 DEBUG Part with id 2 added to Order 22
03.03.2023 - 03:30:33 INFO Order (id=3, part.id=33) is generated
04.04.2024 - 04:40:44 WARN Can't find part 4
05.05.2025 - 05:50:55 ERROR Order 5 cannot be created because a part is missing
То есть, дата-время, далее один из пяти предопределённых уровней логирования и через пробел сообщение. В строках имеются записи об order и part, которые нас интересуют. Как видно, в некоторых сообщениях сначала идёт part и затем order, но в некоторых строках наоборот. Нас интересуют только те сообщения, где после order или part через некоторое количество символов идёт число, которое с ним ассоциируется.
Если я использую следующее выражение:
/^(?<dateTime>.+) (?<level>(?:TRACE|DEBUG|INFO|WARN|ERROR)).*(?:part[^0-9]+(?<part>[0-9]+)?).*(?:order[^0-9]+(?<order>[0-9]+)).*$/gmi
Match 1: 01.01.2021 - 01:10:11 TRACE part.id=11, order.id=1
dateTime: 01.01.2021 - 01:10:11
level: TRACE
part: 11
order: 1
Match 2: 02.02.2022 - 02:20:22 DEBUG Part with id 2 added to Order 22
dateTime: 02.02.2022 - 02:20:22
level: DEBUG
part: 2
order: 22
, то получаю совпадения для тех строк, где part и order определены в том-же порядке, как и в регулярном выражении. Если же указываю квантификатор ?
для группы захвата part (0 или один раз), то строки Order (id=3, part.id=33) is generated
и Order 5 cannot be created because a part is missing
также попадают в группу захвата order. Если же указать квантификатор ?
для группы захвата order, то в группы захвата order и part вообще ничего не попадает, они как будто пропускаются. Если использовать pipe-символ, например так:
(?:(?:part[^0-9]+(?<part>[0-9]+)?)|(?:order[^0-9]+(?<order>[0-9]+)))
, то в группу захвата попадает только одно значение: либо order, либо part.
Каким образом в регулярном выражении определить необязательные группы захвата в произвольном порядке при их наличии в строке не более одного раза?
Поиграться с выражением можно здесь.