Powershell -replace 当替换字符串包含 $+
Posted
技术标签:
【中文标题】Powershell -replace 当替换字符串包含 $+【英文标题】:Powershell -replace when replacement string contains $+ 【发布时间】:2022-01-22 04:47:03 【问题描述】:我正在 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)。
$
chars.,即以编程方式使用 .Replace('$', '$$')
最容易完成(见下文)。
如果both您的搜索字符串和您的替换字符串逐字,请考虑使用[string]
类型的@改为987654324@,如Brandon Olin's helpful answer所示。
警告:.Replace()
默认区分大小写,而-replace
不区分大小写(作为 PowerShell 一般是);使用不同的.Replace()
重载来区分大小写,或者相反,使用PowerShell 中的-creplace
变体来区分大小写。
.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:替换所有以相同Unicode字符开头的不同子字符串(正则表达式?)