例如,如果我有一个名为$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和正则表达式。
2条答案
按热度按时间nfs0ujit1#
Wiktor的回答包含了解决方案的要点,但让我从概念上分解它:
.*?
匹配 * 多行*,因此需要inline regex option(?s)
(Singleline
),以便确保.
也匹配 * 换行符 * 字符(\n
)之后和结束
之前立即 * include * 换行符。\n
)。如果您有可能遇到Windows格式的CLRF(\r\n
)换行符,请使用\r?\n
匹配 * either * 格式,如Wiktor的答案所示。因此:
至于你尝试了什么:
Your own regex101.com page:
m
和s
。因为您使用了
s
,相当于. NET的(?s)
/SingleLine
选项,所以您的正则表达式碰巧在站点上工作,但由于该选项 * 在PowerShell代码中默认未 * 打开,因此它失败了。请参阅下一节了解如何将www.example.com与PowerShell一起使用。regex101.com with PowerShell.
使用regex101.com和PowerShell正则表达式操作:
注意事项:
对PowerShell正则表达式使用以下设置:
在左侧面板**
FLAVOR
下,选择.NET (C#)
**在**
REGULAR EXPRESSION
输入字段**中:gm
)仅选择PowerShell默认应用的选项*;使用**inline regex options作为所有 * 非默认 * 选项,* 作为正则表达式的一部分***;您可以使用单个(?...)
说明符来表示 * 多个 * 选项,例如(?sm)
激活s
和m
:简而言之:对于**
-replace
操作,确保只选择选项gi
(如下图截图所示),对于-match
操作**,只选择**i
**;把它拼出来选择
insensitive
(i
),以匹配PowerShell不区分大小写的默认行为。如果你需要区分大小写的 * 行为,请使用PowerShell中的
c
前缀运算符变体,例如:-creplace
而不是-replace
multi line
(m
)如果需要这种行为(其中
^
和$
匹配多行字符串中 * each line * 的开始和结束),请将(?m)
前置到正则表达式中。如果你正在测试一个正则表达式来与
-match
一起使用(它只会查找 * 第一个 * 匹配),* 取消选择 *global
(g
)选项。注意. NET没有
g
正则表达式选项;是否重复匹配取决于调用 * 哪个API方法 *。在PowerShell中,
-match
总是只查找 * 一个 * 匹配,[1]而-replace
总是查找 * 全部 *(即:行为就像g
生效一样,如JavaScript和PHP等语言所知)。'...'
),因为封闭分隔符是由所选正则表达式风格 * 暗示的,如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 toOut-String
This regex101.com page显示了基于上述指导的完整解决方案;屏幕截图如下:
[1][GitHub issue #7867](https://github.com/PowerShell/PowerShell/issues/7867)提议引入一个
-matchall
运算符,它将查找 all 匹配-虽然该提议已经被批准,但截至PowerShell 7.2.x,还没有人加紧实现它dz6r00yl2#
你需要用
参见this regex demo。* 详情 *:
(?s)
-RegexOptions.Singleline
选项\r?\n
-CRLF或LF行尾(.*?)
-第1组:任何零或多个字符尽可能少\r?\n
-CRLF或LF行尾