#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 name “string”
. 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]