首页 > 解决方案 > RegEx 目标替换为命名捕获

问题描述

给定

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

我可以用

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

并且$matches['tab']将正确地具有值 3。但是,如果我想增加该值,而不影响字符串部分中的 [3],事情会变得更加复杂。我可以$tabIndex = $line.indexOf("[$tab]")用来获取第一次出现的索引,也可以$newLine = ([regex]"\[$tab\]").Replace($line, '[4]', 1)用来只替换第一次出现。但我想知道,有没有办法更直接地解决这个问题?这不是绝对必要的,因为我只想替换初始 {}_ 中的东西,它具有非常一致的形式,所以替换第一个实例是可行的,只是想知道我是否错过了一个更优雅的解决方案,这也可能在不同的情况下需要。

标签: regexpowershell

解决方案


我会稍微更改一下正则表达式,因为不建议将命名捕获与编号捕获混合,所以它变成了这样:

'^\{(?<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)
)

推荐阅读