PowerShell的replace运算符找不到此RegEx模式

yrefmtwq  于 2023-06-25  发布在  Shell
关注(0)|答案(2)|浏览(83)

例如,如果我有一个名为$MarkdownText的文本,其内容如下:
这不在代码块中

Command 1
Command 2
Command 3

这不在代码块中

Command 4
Command 5
Command 6

我试图解析文本中的任何字符串,这些字符串被 Package 在三个反引号中,如下所示:

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是链接。
我是sooo接近完成这个项目,只是坚持在这最后一个标签
PS:我知道有一些库可以更好地完成这类事情,但我正在使用它来学习PowerShell和正则表达式。

nfs0ujit

nfs0ujit1#

Wiktor的回答包含了解决方案的要点,但让我从概念上分解它:

  • 你的方法的主要问题是:由于您尝试使.*?匹配 * 多行*,因此需要inline regex option (?s) ( Singleline ),以便确保.也匹配 * 换行符 * 字符(\n
  • 此外,为了在行格式方面获得所需的替换,您需要在开始之后和结束之前立即 * include * 换行符。
  • 您的解决方案尝试假设输入文件中只有Unix的LF换行符(\n)。如果您有可能遇到Windows格式的CLRF(\r\n)换行符,请使用\r?\n匹配 * either * 格式,如Wiktor的答案所示。

因此:

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

至于你尝试了什么
Your own regex101.com page

  • 使用了错误的正则表达式"flavor"(PHP)
  • 并假设选项在正则表达式本身之外有效,其中一些选项在PowerShell中默认情况下不会打开,即ms

因为您使用了s,相当于. NET的(?s)/SingleLine选项,所以您的正则表达式碰巧在站点上工作,但由于该选项 * 在PowerShell代码中默认未 * 打开,因此它失败了。
请参阅下一节了解如何将www.example.com与PowerShell一起使用。regex101.com with PowerShell.

使用regex101.com和PowerShell正则表达式操作:

注意事项:

  • 虽然regexstorm.net是一个特定于. NET正则表达式(PowerShell构建于此)的类似网站,但多风格(多方言)www.example.com的功能更全面,特别是在可视化匹配及其解释给定正则表达式的能力方面。regex101.com is more fully featured, notably with respect to visualizing the matches and its ability to explain a given regex.
  • 下面的信息假设www.example.com提供 * 没有 * 特定于PowerShell的风格,这在撰写本文时是正确的。regex101.com* * GitHub issue #1838要求将来引入PowerShell风格**。 Currently, the C#-focused .NET flavor must be used, which requires some extra preparatory work.GitHub issue #1838 asks for a PowerShell flavor to be introduced in the future.

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

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

  • 在**REGULAR EXPRESSION输入字段**中:

      • 设置选项**:单击活动正则表达式选项(默认为gm仅选择PowerShell默认应用的选项*;使用**inline regex options作为所有 * 非默认 * 选项,* 作为正则表达式的一部分***;您可以使用单个(?...)说明符来表示 * 多个 * 选项,例如(?sm)激活sm
  • 简而言之:对于**-replace操作,确保只选择选项gi(如下图截图所示),对于-match操作**,只选择**i**;把它拼出来

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

  • 如果你需要区分大小写的 * 行为,请使用PowerShell中的c前缀运算符变体,例如:-creplace而不是-replace

    • 取消选择 * multi linem
  • 如果需要这种行为(其中^$匹配多行字符串中 * each line * 的开始和结束),请将(?m)前置到正则表达式中。

  • 如果你正在测试一个正则表达式来与-match一起使用(它只会查找 * 第一个 * 匹配),* 取消选择 * globalg)选项。

  • 注意. NET没有g正则表达式选项;是否重复匹配取决于调用 * 哪个API方法 *。

  • 在PowerShell中,-match总是只查找 * 一个 * 匹配,[1]而-replace总是查找 * 全部 *(即:行为就像g生效一样,如JavaScript和PHP等语言所知)。

      • 输入或粘贴regex**:
    • 没有 * 任何封闭引号(通常为'...'),因为封闭分隔符是由所选正则表达式风格 * 暗示的,如GUI中所示。
  • 但是,在本例中隐含的引号是 * C#* 逐字字符串字面量(@"..."),这意味着:

  • 您必须转义任何"字符。在正则表达式中嵌入为"",与PowerShell不同(在PowerShell中最好将正则表达式封装在'...'中,在这种情况下嵌入的"需要 * no * 转义;在"..."内部,``"通常用于转义嵌入的",在这种情况下它将 * 不 * 工作;但是,""`也可以在PowerShell中运行)。

  • 如果您原来的'...'封闭的正则表达式包含PowerShell转义的嵌入式'字符,即'',必须替换为',否则 * 两个 * '匹配。

  • 如果您正在测试**-replace操作**,请单击FUNCTION下的Substitution,这将显示SUBSTITUTION * 输入字段 *,您可以在其中键入/粘贴替换表达式(第二个RHS -replace操作数,例如本例中的[code]$1[/code]),同样 * 不带 * 封闭引号。

  • 奇怪的是,转义在这个字段中似乎 * 不 * 是必要的,即使是嵌入的"字符。但是,有关PowerShell转义的'字符的警告。- ''-逐字使用在这里也适用。

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

  • 关于 input(subject)string(field**TEST STRING**)的一个警告是,粘贴 * 多行 * 字符串插入总是将CRLF(Windows格式)转换为LF(Unix)换行符。类似地,当你 * 键入 * 一个多行字符串时,总是创建LF换行符。

  • 始终使用\r?\n作为正则表达式的一部分来匹配 either 换行符形式,可以避免这种行为导致的问题。

  • 但是,由于您只能提供 * 单个 *(可能是多行)输入字符串,因此无法模拟典型的PowerShell行为,即将多行文本作为 * 多个单独(无换行符)行 * 的流提供,就像使用Get-Content(不含-Raw)和调用 * 外部程序 * 作为输入一样。要在PowerShell上提供单个多行字符串,请使用Get-Content -Raw或pipe to Out-String

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

[1][GitHub issue #7867](https://github.com/PowerShell/PowerShell/issues/7867)提议引入一个-matchall运算符,它将查找 all 匹配-虽然该提议已经被批准,但截至PowerShell 7.2.x,还没有人加紧实现它

dz6r00yl

dz6r00yl2#

你需要用

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

参见this regex demo。* 详情 *:

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

相关问题