Выражение регулярного выражения - соответствует заданным c символам (несколько раз) и игнорирует комментарии - PullRequest
0 голосов
/ 22 января 2020

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

Я использую Powershell и его тип [regex], который является C# классом , конечная цель - прочитать файл Toml (примеры данных внизу или использовать эту ссылку для regex101 ), в которой мне нужно:

  • сопоставить некоторые значения (значения между "__")
  • игнорировать комментарии. (комментарий начинается с "#")

Чтобы сопоставить значения и поместить их в группу захвата, работает следующее регулярное выражение:

match the template value (values between "__" ):
__(?<tokenName>[\w\.]+)__

Я также хочу игнорировать комментарии строк, и я придумал это:

Ignore lines that start with a comment (even if "#" is preceded by spaces or tabs):
^(?!\s*\t*#).*

Проблема начинается, когда я их соединяю

^(?!\s*\t*#).*__(?<tokenName>[\w\.]+)__

это выражение имеет следующие проблемы:

  1. до одного совпадения в строке, последнее (ie: в строке с "Prop5 = ..." я получаю одно совпадение вместо двух)

  2. Комментарии в конце строки не рассматриваются (ie: в строке с "Prop4 = ..." два совпадения вместо одного)

Я также пытался

add this at the end of the expression, it should stop the match on the first occurrence of the character
[^#]

add this at the beginning, which should check if the matched string has the given char before it and exclude it
(?<!^#)

Это пример моих данных

#templateFile
[Agent]
    Prop1 = "__Data.Agent.Prop1__"
    Prop2 = [__Data.Agent.Prop2__]
    #I'm a comment
    #Prop3 = "__NotUsed__"
    Prop4 = [__Data.Agent.Prop4__] #sample usage comment __Data.Agent.xxx__
    Prop5 = ["__Data.Agent.Prop5a__","__Data.Agent.Prop5b__"]

Я думаю, что более простым решением будет сопоставить данную строку, только если перед ней не стоит "#" линия. Возможно ли это?

РЕДАКТИРОВАТЬ:

Первое выражение, предложенное @ the-четвертой птицей, работает отлично, ему просто нужно указать модификатор multiline. Окончательный (запускаемый) результат выглядит следующим образом в PowerShell.

[regex]$reg = "(?m)(?<!^.*#.*)__(?<tokenName>[\w.]+)__"

$text = '
#templateFile
[Agent]
    Prop1 = "__Data.Agent.Prop1__"
    Prop2 = [__Data.Agent.Prop2__]
    Prop5 = ["__Data.Agent.Prop5a__","__Data.Agent.Prop5b__"]
    #a comment
    #Prop3 = "__Data.Agent.Prop3__"
    Prop4 = [__Data.Agent.Prop4__] #sample usage comment __Data.Agent.xxx__
'

$reg.Matches($text) | Format-Table
#This returns
Groups         Success Name Captures Index Length Value
------         ------- ---- -------- ----- ------ -----
{0, tokenName}    True 0    {0}         31     20 __Data.Agent.Prop1__
{0, tokenName}    True 0    {0}         62     20 __Data.Agent.Prop2__
{0, tokenName}    True 0    {0}         94     21 __Data.Agent.Prop5a__
{0, tokenName}    True 0    {0}        118     21 __Data.Agent.Prop5b__
{0, tokenName}    True 0    {0}        194     20 __Data.Agent.Prop4__

1 Ответ

1 голос
/ 22 января 2020

Я думаю, вы могли бы использовать бесконечное повторение , чтобы проверить, не содержит ли предшествующее #, чтобы также учесть комментарий в Prop4

(?<!^.*#.*)__(?<tokenName>[\w.]+)__

. Net regex demo

Если в Prop4 должно быть 2 совпадения, вы можете использовать:

(?<!^[ \t]*#.*)__(?<tokenName>[\w.]+)__

. NET regex demo

Для правильной работы обоим выражениям требуется модификатор multiline. это может быть указано inline путем добавления (? m) в начале. (или указав его в конструкторе, который его поддерживает)

(?m)(?<!^.*#.*)__(?<tokenName>[\w.]+)__
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...