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

Posted

技术标签:

【中文标题】如何在 RegEx 替换中将 RegEx 令牌传递给 PowerShell 子表达式?【英文标题】:How do I pass a RegEx token to a PowerShell subexpression in a RegEx substitution? 【发布时间】:2021-07-30 09:28:19 【问题描述】:

我有以下代码:-

'\u0026' -replace '(\u)(\d4)', '$$([char]0x$2)'

这显然会导致:-

$([char]0x0026)

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

'\u0026' -replace '(\\u)(\d4)', "$([char]0x`$2)"

然后我会得到:-

表达式或语句中出现意外的标记“0x`$”。

如果我将事情简化为:-

'\u0026' -replace '(\\u)(\d4)', "0x`$2"

那么我可以得到:-

0x0026

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

'\u0026' -replace '(\\u)(\d4)', "$([char]0x0026) 0x`$2"

然后会出现以下结果:-

&0x0026

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

我是 RegEx 的新手。我已经达到我的极限了吗?

【问题讨论】:

也许你应该解释你想要做什么,而不是你是怎么做的。 (见:What the XY problem?) 啊,所以你想修改文件中的 html 源代码?您能否在问题中包含此类文件的示例? 我完全同意@Tomalak,提出的问题是XY problem。要摆脱这个XY 循环,问问自己WHY???(问题中的每个定义)?如:为什么要“& 0x0026”? (并将该信息添加到问题中)。我猜你只是想这样做:[Regex]::Unescape('Jack\u0026Jill')。但即使这样也是一个有问题的答案,因为通常不需要unescape 一个正则表达式...... 我们仍然没有解决您的实际问题,而只是解决了它的症状。没有理由为什么\u0026 甚至会出现在 HTML 中,除非在生成 HTML 时出现问题(那么这应该被修复),或者它在 JSON 字符串中(然后应该使用 JSON 解析器)。通过正则表达式替换这些转义序列是可能的,但它根本不像您真正需要的东西。 @Tomalak - 你是对的,未来也不会有任何修复它的计划,但这不在我的掌控之中。 Intranet 页面是 Sharepoint 页面,我在某处读到某些字符会以这种方式转义。很抱歉没有正确解释背景场景,但我非常感谢大家对此的投入。作为我自己在这个网站上的第一个 OP,我会学习我的错误,下次会更清楚。 【参考方案1】:

显然,您想要 unescape 一个 转义 正则表达式。您可以使用 .net [regex] unescape 方法来做到这一点:

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

产量:

Jack&Jill

【讨论】:

【参考方案2】:

在 powershell 7 中有一种方法,其中 -replace 的第二个参数可以是一个脚本块。使用$_ 获得第二个匹配组需要更多工作:

'\u0026' -replace '(\\u)(\d4)',  $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)(\d4)',  [char][int]('0x' + $_.groups[2]) 

&

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

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

+

【讨论】:

【参考方案3】:

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

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

在早期版本的 PowerShell 中,您可以通过调用 [Regex]::Replace() 来执行相同操作:

[regex]::Replace('\u0026', '(\\u)(\d4)', param($m) "0x$($m.Groups[2].Value)")

在这两种情况下,该块将充当每个匹配项的回调,允许您构造替换字符串 after 访问匹配的子字符串,但 before 替换发生:

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

【讨论】:

以上是关于如何在 RegEx 替换中将 RegEx 令牌传递给 PowerShell 子表达式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用 Regex 将 [number] 替换为 number - 1?

如何剪切部分文本并用Python和RegEx替换每一行

使用贪婪令牌保留 REGEX 分隔符

在sublime text和vs code中使用Regex进行替换的方式

如何将 JSON 中的值替换为 RegEx 在使用 Python 的文件中找到的值?

如何使用Java replaceAll(regex,replacement)方法替换字符串中的所有方括号[重复]