Powershell -replace 当替换字符串包含 $+

Posted

技术标签:

【中文标题】Powershell -replace 当替换字符串包含 $+【英文标题】:Powershell -replace when replacement string contains $+ 【发布时间】:2020-05-20 20:34:12 【问题描述】:

我正在 PowerShell 中进行字符串替换。我无法控制被替换的字符串,但我可以通过这种方式重现我遇到的问题:

> 'word' -replace 'word','@#$+'
@#word

当我需要的实际输出是

> 'word' -replace 'word','@#$+'
@#$+

字符串$+ 正在扩展为要替换的单词,我无法找到阻止这种情况发生的方法。我试过用\(好像它是一个正则表达式)转义$,用反引号`(就像正常的PowerShell方式一样)。例如:

> 'word' -replace 'word',('@#$+' -replace '\$','`$')
@#`word

如何在 PowerShell 中用文字 $+ 替换?值得一提的是,我正在运行 PowerShell Core 6,但这也可以在 PowerShell 5 上重现。

【问题讨论】:

'word'.Replace('word','@#$+')也是如此 【参考方案1】:

您可以像这样使用.Replace() 方法,而不是使用-replace 运算符:

PS> 'word'.Replace('word','@#$+')
@#$+

.Replace() 方法来自 .NET String 类,而 -Replace 运算符是使用 System.Text.RegularExpressions.Regex.Replace() 实现的。

更多信息在这里:https://vexx32.github.io/2019/03/20/PowerShell-Replace-Operator/

【讨论】:

【参考方案2】:

我找不到它的文档,但“Visual Basic”样式转义规则有效,重复字符。

'word' -replace 'word','@#$$+'给你:@#$+

【讨论】:

遗憾的是,它并没有按我希望的方式工作。当我运行'word' -replace 'word',('@#$+' -replace '$','$$') 时,它最终运行时会进行相同的扩展。我无法修改源字符串,所以我必须使用replace @MarkHenderson:您的替换表达式有缺陷:它必须是 ('@#$+' -replace '\$','$$$$')(原文如此),或者更简单地说,'@#$+'.Replace('$','$$') 确实,$$ 有效;它记录在here $$$$ 版本确实有效。我已经发布了我的人为示例,因此尽管看起来我可以使用您的简化版本,但我认为我不能。但是 $$$$ 替换有效。我认为这样的一行需要非常详细的评论;) @MarkHenderson:评论只是对my answer详细解释的总结。【参考方案3】:

令人困惑的是,这些代码没有记录在“关于比较运算符”下。除了我在下面有一个关于它们的封闭错误报告,如果你看,'哇,所有这些 - 替换第二个参数代码都记录在哪里?'。 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7 这已成为 我的 参考。 “$+” 表示“替换捕获的最后一个子匹配”。将美元符号加倍有效,'替换单个“$”文字':

'word' -replace 'word','@#$$+'

@#$+

或者在 PS 6 及更高版本中使用第二个参数的 scriptblock 版本(可能会更慢):

'word' -replace 'word','@#$+'

【讨论】:

我建议明确说明脚本块技术具有显着的性能影响(在单个调用中无关紧要,但可能在循环中/在 LHS 阵列上操作时)。 原来信息那里,只是不容易被发现,在about_Regular_Expressions主题内:Substitutions in Regular Expressions:;我创建了a GitHub issue,建议对about_Comparison_Operators 主题进行具体改进。【参考方案4】:

tl;dr

加倍替换操作数中的$ 以使用它逐字逐句

PS> 'word' -replace 'word', '@#$$+' # note the doubled '$'
@#$+

PowerShell 的-replace operator

使用 regex (regular expression) 作为 搜索(第一个)操作数

如果您希望不使用搜索字符串逐字,则必须转义: 以编程方式:使用 [regex]::Escape() 或者,在字符串文字中,您可以或者\-escape 单个字符,否则被解释为正则表达式元字符。

使用非文字字符串,可以引用正则表达式匹配的内容作为替换(第二个)操作数,通过$-前缀标记,例如$&$+(参见上面的链接或Substitutions in Regular Expressions)。

使用替换字符串verbatimdouble任何$ chars.,即以编程方式使用 .Replace('$', '$$') 最容易完成(见下文)。

如果both您的搜索字符串您的替换字符串逐字,请考虑使用[string]类型的@改为987654324@,如Brandon Olin's helpful answer所示。

警告:.Replace() 默认区分大小写,而-replace 不区分大小写(如 PowerShell 一般是);为不区分大小写使用不同的.Replace() 重载,或者相反,使用PowerShell 中的-creplace 变体来区分大小写。

[PowerShell (Core) 7+ only] 大小写-不敏感 .Replace() 示例:'FOO'.Replace('o', '@', 'CurrentCultureIgnoreCase')

.Replace() 只接受一个单个字符串作为输入,而-replace接受一个字符串数组 > 作为 LHS;例如:

'hi', 'ho' -replace 'h', 'f' # -> 'fi', 'fo'

.Replace()-replace 快,尽管这只在迭代次数较多的循环中很重要。


如果您坚持使用 -replace 运算符

如上所述,加倍替换操作数中的 $ 可确保在替换操作数中逐字处理它们:

PS> 'word' -replace 'word', '@#$$+' # note the doubled '$$'
@#$+

要以编程方式进行这个简单的转义,您可以利用.Replace() 方法:

'word' -replace 'word', '@#$+'.Replace('$', '$$')

你也可以用 nested -replace 操作来做到这一点,但这会变得笨拙(\$ 在正则表达式中转义 $$$ 表示 单个 $ 在替换字符串中):

# Same as above.
'word' -replace 'word', ('@#$+' -replace '\$', '$$$$')

换一种说法:相当于:

'word'.Replace('word', '@#$+')

是(注意-replace 运算符-creplace 的大小写敏感变体的使用):

'word' -creplace [regex]::Escape('word'), '@#$+'.Replace('$', '$$')

但是,如上所述,如果要逐字使用搜索字符串和替换操作数,则最好使用.Replace(),既简洁又性能好。

【讨论】:

以上是关于Powershell -replace 当替换字符串包含 $+的主要内容,如果未能解决你的问题,请参考以下文章

powershell 替换连接字符串

字符串替换在powershell中不起作用

Powershell:替换所有以相同Unicode字符开头的不同子字符串(正则表达式?)

在 .bat 文件中使用 PowerShell,将一个字符串替换为多个字符串

使用 Powershell 替换将字符插入 UNC 字符串

如何使用PowerShell替换文件中的多个字符串