Целевая замена регулярных выражений на именованные захваты

#regex #powershell

#регулярное выражение #powershell

Вопрос:

Учитывая

 $line = '{initError-[cf][3]}_Invalid nodes(s): [3]'
  

Я могу использовать

 $line -match '^{(?<type>[a-z] )(-[(?<target>(C|F|CF))])?([(?<tab>d )])?}_(?<string>.*)'
  

И $matches['tab'] будет корректно иметь значение 3. Однако, если я затем захочу увеличить это значение, не затрагивая также [3] в разделе string, все становится сложнее. Я могу использовать $tabIndex = $line.indexOf("[$tab]") для получения индекса первого вхождения, и я также могу использовать $newLine = ([regex]"[$tab]").Replace($line, '[4]', 1) для замены только первого вхождения. Но мне интересно, есть ли способ добраться до этого более напрямую? Это не является строго необходимым, поскольку я всегда захочу заменять объекты только в пределах начального {}_ , который имеет очень согласованную форму, поэтому замена первого экземпляра работает, просто интересно, не упускаю ли я более элегантное решение, которое также может понадобиться в другой ситуации.

Комментарии:

1. Вы просто хотите увеличить все числа в квадратных скобках? Обратите внимание, что вы не можете заменить группу напрямую, они предназначены для извлечения текста, а не для замены. Обычно вы фиксируете то, что вам нужно сохранить , и просто сопоставляете то, что вам нужно удалить .

2. Попробуйте $callback = { param($m) '[' ([convert]::ToInt32($m.Groups[1].Value, 10) 1) ']' } => $regex=[regex]'[(d )]' => $regex.Replace($line, $callback)

Ответ №1:

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

 '^{(?<type>[a-z] )(?:-[(?<target>[CF]{1,2})])?(?:[(?<tab>d )])?}_(?<string>.*)'
  

Затем вы могли бы использовать это, как показано ниже, для замены tab значения:

 $line        = '{initError-[cf][3]}_Invalid nodes(s): [3]'
$newTabValue = 12345

$line -replace '^{(?<type>[a-z] )(?:-[(?<target>[CF]{1,2})])?(?:[(?<tab>d )])?}_(?<string>.*)', "{`${type}-[`${target}][$newTabValue]}_`${string}"
  

Результатом этого будет:

{initError-[cf][12345]}_Invalid nodes(s): [3]

Сведения о регулярных выражениях:

 ^                    Assert position at the beginning of the string
{                   Match the character “{” literally
(?<type>             Match the regular expression below and capture its match into backreference with name “type”
   [a-z]             Match a single character in the range between “a” and “z”
                     Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
(?:                  Match the regular expression below
   -                 Match the character “-” literally
   [                Match the character “[” literally
   (?<target>        Match the regular expression below and capture its match into backreference with name “target”
      [CF]           Match a single character present in the list “CF”
         {1,2}       Between one and 2 times, as many times as possible, giving back as needed (greedy)
   )
   ]                Match the character “]” literally
)?                   Between zero and one times, as many times as possible, giving back as needed (greedy)
(?:                  Match the regular expression below
   [                Match the character “[” literally
   (?<tab>           Match the regular expression below and capture its match into backreference with name “tab”
      d             Match a single digit 0..9
                     Between one and unlimited times, as many times as possible, giving back as needed (greedy)
   )
   ]                Match the character “]” literally
)?                   Between zero and one times, as many times as possible, giving back as needed (greedy)
}                   Match the character “}” literally
_                    Match the character “_” literally
(?<string>           Match the regular expression below and capture its match into backreference with namestring”
   .                 Match any single character that is not a line break character
      *              Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
)
  

Ответ №2:

Альтернативным способом увеличения первого числа в скобках является использование -Split оператора для доступа к номеру, который вы хотите изменить:

 $line = '{initError-[cf][3]}_Invalid nodes(s): [3]'
$NewLine = $line -split "(d )"
$NewLine[1] = [int]$newLine[1]   1
-join $NewLine
  

Вывод:

 {initError-[cf][4]}_Invalid nodes(s): [3]