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

Powershell -replace when replacement string contains $+

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

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

当我需要的实际输出是

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

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

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

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

除了使用 -replace 运算符,您还可以使用 .Replace() 方法,如下所示:

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

.Replace() 方法来自 .NET String class 而 -Replace 运算符是使用 System.Text.RegularExpressions.Regex.Replace().

实现的

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

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

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

tl;dr:

$ 加倍 $ 在您的替换操作数中使用它 逐字 :

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

PowerShell 的 :

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

    • 如果你想o使用搜索字符串逐字,你必须转义:
      • 以编程方式:使用 [regex]::Escape()
      • 或者,在字符串文字中,你可以或者\转义个别字符否则将被解释为正则表达式元字符。
  • 使用 非文字字符串, 可以引用正则表达式匹配的内容 作为 替换(第二个)操作数,通过$-前缀标记,例如$&$+(参见link 以上或 Substitutions in Regular Expressions).

    • 使用替换字符串逐字,double任何$ chars. in it,这是 programmatically 最容易用 .Replace('$', '$$') 完成(见下文) .

如果同时您的搜索字符串您的替换字符串将被使用逐字,考虑使用 [string] 类型的 .Replace() method instead, as shown in .

  • 注意:.Replace()默认是大小写敏感的,而-replace是大小写insensitive(与 PowerShell generally 一样);使用不同的 .Replace() 重载来区分大小写,或者相反地,使用 PowerShell 中的 -creplace 变体来区分大小写。

    • [仅限 PowerShell (Core) 7+] 大小写-不敏感 .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(),以保证简洁和性能。

令人困惑的是,这些代码为何未记录在 "about comparison operators" 下。除了我下面有一个关于它们的已关闭错误报告,如果你看的话,'wow, where are all these -replace 2nd argument codes documented?'。 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7 这已成为 我的 参考。 “$+”表示 "Substitutes the last submatch captured"。将美元符号加倍有效,'substitutes a single "$" literal':

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

@#$+

或者在PS6及以上版本中使用第二个参数的脚本块版本(可能更慢):

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