如何将 RegEx 令牌传递给 RegEx 替换中的 PowerShell 子表达式?

How do I pass a RegEx token to a PowerShell subexpression in a RegEx substitution?

我有以下代码:-

'\u0026' -replace '(\u)(\d{4})', '$$([char]0x)'

这显然会导致:-

$([char]0x0026)

如果我将 RegEx 替换为可扩展字符串:-

'\u0026' -replace '(\u)(\d{4})', "$([char]0x`)"

那么我会得到:-

Unexpected token '0x`$' in expression or statement.

如果我将事情简化为:-

'\u0026' -replace '(\u)(\d{4})', "0x`"

然后我可以得到:-

0x0026

但是,我想要的是将“0x0026”转换为一个字符,以便将“\u0026”替换为“&”。但是,似乎不可能以这种方式将 RegEx 替换标记传递给 PowerShell 子表达式。如果您将两种语言分开:-

'\u0026' -replace '(\u)(\d{4})', "$([char]0x0026) 0x`"

则结果如下:-

& 0x0026

这很棒,因为它表明 PowerShell 子表达式在 RegEx 替换中确实有效,如转换后的 & 符号所示。

我是正则表达式的新手。我已经达到极限了吗?

使用脚本块替换(6.2 及更高版本):

'\u0026' -replace '(\u)(\d{4})', {"0x$($_.Groups[2].Value)"}

在早期版本的 PowerShell 中,您可以通过调用 [Regex]::Replace():

来实现相同的目的
[regex]::Replace('\u0026', '(\u)(\d{4})', {param($m) "0x$($m.Groups[2].Value)"})

在这两种情况下,该块都将作为每个匹配项的回调,允许您在 访问匹配的子字符串后构造替换字符串,但是 替换发生之前:

PS ~> [regex]::Replace('\u0026', '(\u)(\d{4})', {param($m) "0x$($m.Groups[2].Value)"})
0x0026

powershell 7 中有一种方法,其中 -replace 的第二个参数可以是脚本块。使用 $_:

获取第二个匹配组需要做更多的工作
'\u0026' -replace '(\u)(\d{4})', { $b = $_ }
$b.groups

Groups   : {0, 1, 2}
Success  : True
Name     : 0
Captures : {0}
Index    : 0
Length   : 6
Value    : \u0026

Success  : True
Name     : 1
Captures : {1}
Index    : 0
Length   : 2
Value    : \u

Success  : True
Name     : 2
Captures : {2}
Index    : 2
Length   : 4
Value    : 0026


'\u0026' -replace '(\u)(\d{4})', { [char][int]('0x' + $_.groups[2]) }

&

请注意,\d 不会匹配所有十六进制数。 ([[:xdigit:]] 无效。)

'\u002b' -replace '(\u)([0-9a-f]{4})', { [char][int]('0x' + $_.groups[2]) }

+

显然,您想要 unescapeescaped 正则表达式。您可以使用 .net [regex] unescape 方法执行此操作:

[Regex]::Unescape('Jack\u0026Jill')

产量:

Jack&Jill