【问题标题】:Powershell Regex - Replace between string A and string B only if contains string CPowershell Regex - 仅当包含字符串 C 时才在字符串 A 和字符串 B 之间替换
【发布时间】:2021-09-29 00:55:32
【问题描述】:

我有一个看起来像这样的文件

ABC01|01
Random data here 2131233154542542542
More random data
STRING-C
A bit more random stuff
&(%+
ABC02|01
Random data here 88888888
More random data 22222
STRING-D
A bit more random stuff
&(%+

我正在尝试编写一个脚本来查找 ABC01&(%+ 之间的所有内容如果它包含 STRING-C

我想出了这个正则表达式ABC([\s\S]*?)STRING-C(?s)(.*?)&\(%\+

我从带有get-content 的文本文件中获取此内容。

$bad_content = gc $bad_file -raw

我想做类似($bad_content.replace($pattern,"") 的操作来删除正则表达式匹配。

如何将文件中的匹配项替换为空?我什至不确定我的正则表达式是否正确,但在 regex101 上它似乎找到了我需要的字符串。

【问题讨论】:

    标签: regex powershell


    【解决方案1】:

    您的正则表达式适用于给定的示例输入,但不是稳健,因为如果块的顺序颠倒,它会错误地匹配 块并删除 两者

    Tim Biegeleisen's helpful answer 显示了一个通过否定前瞻断言 ((?!...)) 解决问题的正则表达式。

    让我展示如何通过 PowerShell 使其工作:

    • 您需要使用基于正则表达式的-replace operator,而不是基于文字子字符串的.Replace() method:[1] 来应用它。

    • 要从文件中读取输入字符串,请使用Get-Content-Raw 开关确保文件被读取为单行多行字符串;默认情况下,Get-Content 返回一个行数组(流),这将导致-replace 操作单独应用于每一行

    (Get-Content -Raw file.txt) -replace '(?s)ABC01(?:(?!&\(%\+).)*?STRING-C.*?&\(%\+'
    

    未指定替换文本(作为-replace 的可选第二个RHS 操作数)将匹配替换为空字符串,因此有效地删除 匹配的内容。

    从蒂姆的答案借来的正则表达式被简化了一点,通过使用指定匹配选项的内联方法来调整表达式开头的 single-line 选项 ((?s)),这使得后续的. 实例也匹配换行符(比[\s\S] 更短、更有效的替代方案)。


    [1] 请参阅 this answer 了解两者的并列情况,包括何时使用 which 的指导。

    【讨论】:

    • 很高兴听到这个消息,@shadow2020。感谢Tim Biegeleisen 提出了强大的正则表达式。
    【解决方案2】:

    我们可以在两个标记之间匹配时使用缓和点技巧,以确保在匹配STRING-C之前不会越过结束标记:

    ABC01(?:(?!&\(%\+)[\s\S])*?STRING-C[\s\S]*?&\(%\+
    

    Demo

    下面是正则表达式模式的解释:

    ABC01                   match the starting marker
    (?:(?!&\(%\+)[\s\S])*?  without crossing the ending marker
    STRING-C                match the nearest STRING-C marker
    [\s\S]*?                then match all content, across lines, until reaching
    &\(%\+                  the ending marker
    

    【讨论】:

    • 喜欢这个解决方案,但我得到的结果与我自己的模式相同。如果我这样做,[regex]::match($pattern, $exampledata) 我会得到一个 STRING-C 的值,没有别的。我需要替换整个文本,而不仅仅是字符串-c
    • 如果您检查正则表达式演示链接,您会发现实际上我的模式匹配从开始到结束标记的整个块。 Powershell 肯定还有其他的(遗憾的是我的使用经验为零)。
    • @shadow2020 Tim 的正则表达式工作得很好,你应该做[regex]::Matches($exampledata, $pattern) 而不是反之亦然。
    猜你喜欢
    • 2021-06-02
    • 2021-08-19
    • 1970-01-01
    • 2022-01-22
    • 2021-10-31
    • 2021-03-11
    • 1970-01-01
    相关资源
    最近更新 更多