Комплекс именной спичечной группы RegEx обзор - PullRequest
0 голосов
/ 28 января 2019

Из этого примера строка

$logLine = '{header[3]}_Pragmatic Praxis Initialization Log'

Я пытаюсь извлечь три куска данных

  • header как тип
  • 3 как(необязательно) значение табуляции
  • все после этого _ в виде строки

Теперь у меня есть

$logLine = '{header[3]}_Pragmatic Praxis Initialization Log'
if ($logLine -match '^\{(?<type>[a-z]+)(?:\[?(?<tab>\d?)\]?)\}_(?<string>.+)$') { 
    Write-Host "$($matches['type'])"
    Write-Host "$($matches['tab'])"
    Write-Host "$($matches['string'])"
}

И это работает хорошо.Но я настолько неквалифицирован в RegEx, и это, безусловно, самый сложный RegEx, который я когда-либо строил с нуля, поэтому мне интересно, видит ли кто-нибудь хитрость в этом подходе, которого я не вижу?

Илимне нужно открыть немного вина и отпраздновать достижение какого-то веха в понимании RegEx?

РЕДАКТИРОВАТЬ: Таким образом, мой успех сделал меня более уверенным.Я решил сделать Tab обязательным, но добавить дополнительную цель, которая может быть «консоль» или «файл».Итак, я сделал это

$logLine = '{header[3]}_Pragmatic Praxis Initialization Log'
if ($logLine -match '^\{(?<type>[a-z]+)(?:-(?<target>(console|file)))\[(?<tab>\d*)\]\}_(?<string>.+)$') { 
    Write-Host "$($matches['type'])"
    Write-Host "$($matches['target'])"
    Write-Host "$($matches['tab'])"
    Write-Host "$($matches['string'])"
}

, который работает, когда цель присутствует, но не работает, когда ее нет.Похоже, я научился чему-то, а не праздновал.;)

РЕДАКТИРОВАТЬ # 2: За @Ansgar Wiechers, я действительно неправильно понял (?:...), специально путая его с (....)?.Исходя из этого, это мой пересмотренный шаблон, который, кажется, делает то, что я хочу.Я все еще могу сделать и target, и tab обязательными, поскольку я думаю, что это делает код более читабельным, а также упрощает шаблон RegEx, но все же хорошо, чтобы он работал, как я изначально предполагал, что он тоже будет работать.

if ($logLine -match '^\{(?<type>[a-z]+)(-(?<target>(console|file)))?(\[(?<tab>\d+)\])?\}_(?<string>.+)') { 
    Write-Host "$($matches['type'])"
    Write-Host "$($matches['target'])"
    Write-Host "$($matches['tab'])"
    Write-Host "$($matches['string'])"
}

1 Ответ

0 голосов
/ 28 января 2019

Похоже, вы не понимаете, что делает (?:...).Эта конструкция определяет не необязательное совпадение, а группу без захвата .(Под) выражение (?:-(?<target>console|file)) потребует, чтобы строка содержала -console или -file и возвращала console или file (без начального дефиса) в качестве именованного совпадения "target".Чтобы сделать группу необязательной, вам нужно добавить еще ? после группы.

^\{(?<type>[a-z]+)(?:-(?<target>console|file))?\[(?<tab>\d*)\]\}_(?<string>.+)
#                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

Обратите внимание, что конечное выражение .+ или .* делает привязку выражения кконец строки ($) не имеет смысла, поэтому просто удалите $ из конца вашего выражения.

Вам также не понадобится вложенная (неназванная) группа захвата вокруг console|file.Указанная группа захвата является достаточной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...