【问题标题】:Powershell -replace when replacement string contains $+Powershell -replace 当替换字符串包含 $+
【发布时间】: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','@#$+')也是如此

标签: powershell replace string-literals


【解决方案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(),既简洁又性能好。

    【讨论】:

      猜你喜欢
      • 2017-03-06
      • 2013-11-30
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      相关资源
      最近更新 更多