【问题标题】:PowerShell's replace operator fails to find this RegEx patternPowerShell\ 的替换运算符无法找到此 RegEx 模式
【发布时间】:2022-08-18 09:07:19
【问题描述】:

例如,如果我有一个名为 $MarkdownText 的文本,其内容是:


这不在代码块中

Command 1
Command 2
Command 3

这不在代码块中

Command 4
Command 5
Command 6

我正在尝试解析文本中包含在三个反引号对中的任何字符串,如下所示:

This is not in a code block

[code]
Command 1
Command 2
Command 3
[/code]

This is not in a code block
[code]
Command 4
Command 5
Command 6
[/code]

到目前为止,我在 PowerShell 中的代码是:

$MarkdownText = Get-Content -Path \"./codebloack.md\" -Raw

$MarkdownText -Replace \'```\\n(.*?)\\n```\', \'[code]$1[/code]\' | Set-Content -Path .\\Output.txt

当我运行这两行时,我根本没有收到任何错误 Powershell 创建 Output.txt 文件但没有任何更改,它与输入文件完全相同。

我的 RegEx 在 RegE101 上匹配得很好,HERE 是链接。

我非常接近完成这个项目,只是停留在最后一个标签上

PS:我知道有些库会以更好的方式做这类事情,但我正在使用它来学习 PowerShell 和正则表达式。

    标签: regex powershell


    【解决方案1】:

    Wiktor 的回答包含解决方案的要点,但让我在概念上对其进行分解:

    • 您的方法的主要问题是:因为您正在尝试使.*? 匹配多行,你需要inline regex option (?s) (Singleline),所以确保. 也匹配新队字符 (\n)

    • 此外,要在行格式方面获得所需的替换,您需要包括在打开之后和关闭之前的换行符```

    • 您的解决方案尝试在输入文件中假设 Unix 格式的仅 LF 换行符 (\n)。如果您可能还会遇到 Windows 格式的 CLRF (\r\n) 换行符,请使用 \r?\n 匹配任何一个格式,如 Wiktor 的回答中所示。

    所以:

    $MarkdownText -replace '(?s)```(\r?\n.*?\r?\n)```', '[code]$1[/code]'
    

    至于你尝试了什么

    Your own regex101.com page:

    • 使用了错误的正则表达式“风味”(PHP),
    • 并假定选项生效在正则表达式本身之外,其中一些在 PowerShell 中默认不开启,即ms

    因为您使用了s,相当于.NET 的(?s) / SingleLine 选项,所以您的正则表达式恰好在该站点上工作,但由于该选项不是默认情况下在 PowerShell 代码中打开,它在那里失败。

    请参阅下一节了解如何将 regex101.com 与 PowerShell 一起使用。


    regex101.com 与 PowerShell 正则表达式操作一起使用:

    笔记:

    • 虽然regexstorm.net 是一个类似的网站,专门针对 .NET 正则表达式(PowerShell 建立在它之上),但多风格(多方言)regex101.com 的功能更全面,特别是在可视化匹配和它的能力方面解释给定的正则表达式。

    • 以下信息假设 regex101.com 提供特定于 PowerShell 的风格,在撰写本文时是正确的。目前,必须使用以 C# 为中心的 .NET 风格,这需要一些额外的准备工作。GitHub issue #1838 要求将来引入 PowerShell 风格.

    使用以下PowerShell 正则表达式的设置

    • 在下面FLAVOR在左侧面板上,选择.NET (C#)

    • 在里面REGULAR EXPRESSION 输入栏

      • 设置选项:单击活动的正则表达式选项(默认为gm)以仅选择 PowerShell 应用的那些选项默认;利用inline regex options 所有人非默认选项,作为您的正则表达式的一部分;您可以使用单个 (?...) 说明符选项,例如(?sm) 同时激活 sm

        • 简而言之:对于一个-replace操作,确保只有选项gi被选中(如下面的屏幕截图所示),对于-match操作, 只用i;拼写出来:

        • 选择 insensitive (i),以匹配 PowerShell 不区分大小写的默认行为。

          • 如果您需要案例-敏感的行为,在 PowerShell 中使用 c-prefixed 运算符变体,例如-creplace 而不是 -replace
        • 取消选择multi line (m)

          • 如果您需要这种行为(其中^$ 匹配每一行在多行字符串中),将(?m) 添加到您的正则表达式中。
        • 如果您正在测试与 -match 一起使用的正则表达式(它只会寻找第一的匹配),取消选择global (g) 选项。

          • 请注意,.NET 没有 g 这样的正则表达式选项;是否进行重复匹配取决于哪个 API 方法你打电话。

          • 在 PowerShell 中,-match 总是只寻找匹配,[1]-replace 总是寻找全部(即,就像 g 生效一样,正如 JavaScript 和 PHP 等语言所知的那样)。

      • 输入或粘贴您的正则表达式

        • 没有任何封闭的引号(通常是'...'),因为封闭的分隔符是默示通过所选的正则表达式风格,如 GUI 中所示。

        • 但是,在这种情况下,隐含的引用是C#逐字字符串文字 (@"..."),这意味着:

          • 你必须转义任何 " 字符。嵌入到您的正则表达式中为"",不像在 PowerShell 中(最好将正则表达式包含在 '...' 中,在这种情况下嵌入 " 需要逃跑;在"..." 内部,`" 通常用于转义嵌入的",这将不是在这种情况下工作;但是,"" 也可以在 PowerShell 中使用)。

          • 如果您最初的 '...'-enclosed 正则表达式包含 PowerShell 转义的嵌入式 ' 字符,即 '',则必须将它们替换为 ',否则' 将被匹配。

    • 如果你正在测试一个-replace操作, 点击SubstitutionFUNCTION,这使得SUBSTITUTION输入字段出现,您可以在其中键入/粘贴替换表达式(第二个 RHS -replace 操作数,例如 [code]$1[/code] 在这种情况下),再次没有附文。

      • 奇怪的是,出现了逃跑不是在这个领域是必要的,甚至不是嵌入的" 字符。但是,警告是 PowerShell 转义的 ' 字符。 - '' - 逐字使用也适用于此。

      • 替换的结果直接显示在输入字段的下方。

    This regex101.com page 显示了基于上述指导的完整解决方案;屏幕截图如下:


    [1] GitHub issue #7867 建议引入一个 -matchall 运算符来查找全部匹配 - 虽然该提案已获批准,但从 PowerShell 7.2.x 开始,还没有人加紧实施它

    【讨论】:

    • 很棒的文档。非常好
    • 你们这些stackoverflow的家伙真是一个慷慨的人。我想知道如何打开 Powershells RegEX 修饰符分配(因为我可以在 RegEx101 上轻松做到这一点)所以让 RegEx101 符合 powershell 是一个绝妙的主意。感谢分配这篇精彩的文章。
    【解决方案2】:

    你需要使用

    (?s)```\r?\n(.*?)\r?\n```
    

    this regex demo细节

    • (?s) - RegexOptions.Singleline 选项
    • ``` - 三个反引号
    • \r?\n - CRLF 或 LF 行结尾
    • (.*?) - 第 1 组:尽可能少的任何零个或多个字符
    • \r?\n - CRLF 或 LF 行结尾
    • ``` - 三个反引号

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多