PowerShell正则表达式与“其他”正则表达式有何不同?

3
我有一个PowerShell脚本,用于匹配以下正则表达式:
---\n(0[1-9]|1[0-2][\/](0[1-9]|[12]\d|3[01])[\/]\d{2}[\s\S]+?)-----

匹配的字符串来自以下日志文件片段:
10/26/16 11:41:26 - 进程(15925376.4) 用户(mqm) 程序(amqzmuc0) 主机(aixmq1) 安装(Installation1) VRMF(8.0.0.4) 队列管理器(ecs.queue.manager) AMQ6287: WebSphere MQ V8.0.0.4 (p800-004-151017).
解释:WebSphere MQ系统信息:主机信息 :- AIX 7.1 (MQ AIX 64位) 安装 :- /usr/mqm (Installation1) 版本 :- 8.0.0.4 (p800-004-151017) 操作:无。
在perl和regexr.com中使用这个正则表达式,它可以完美地匹配日志文件片段中的两个部分。
现在我已经在powershell中实现了相同的正则表达式,除非我删除\n前面的减号,否则它将不会返回任何匹配。如果我用一个只包含减号的匹配组替换这些减号,它也可以工作。
为了保持一致性并理解正在发生的事情,我需要了解为什么匹配行为在powershell中如此不同。为什么只要开头有减号就不匹配?
以下.NET正则表达式测试程序显示与powershell相同的行为:

http://regexstorm.net/tester

请问有人能解释一下为什么PowerShell中的匹配行为与Perl/regexr.com有这么大的不同吗?
这是我目前正在使用的PowerShell代码片段来匹配该正则表达式:
$matches = ([regex]::matches($sInput, "---\n(0[1-9]|1[0-2][\/](0[1-9]|[12]\d|3[01])[\/]\d{2}[\s\S]+?)\n-") | %{$_.value});

我可以问一下你的正则表达式中第一个选择项 0[1-9] 的意义吗?它唯一的作用就是匹配一个行前有连字符行,包含数字 0109,直接跟着另一个连字符行的行。 - SamWhan
1个回答

3
在Windows上,行末通常是CRLF(两个字符,回车然后换行),而在基于Unix的操作系统(基本上除了Windows之外的任何东西)中,它只是一个换行符LF。转义序列\n指的是LF。要匹配CR,请使用\r
所以我认为正在发生的事情是,如果您的输入包含CRLF,则-\n将无法匹配它。但是\n会匹配它,因为它跳过了前面的CR
您用来测试的网站可能会转换行尾,或者不正确地保留它们,因此会匹配,而.Net测试器可能会做相反的操作。
供参考,每当我需要在正则表达式中匹配行尾时,我使用\r?\n(一个可选的CR后面跟一个LF),这样我就可以捕获两种类型的行尾。
因此,在您的示例中,如果您的特定问题的判断是正确的,那么您应该能够将正则表达式的开头从---\n更改为---\r?\n,并使其起作用。

1
或者像这个regex101的例子一样,只需输入\s*,就可以安全地匹配任何组合。 - SamWhan
@ClasG 我会说用\s+,因为\s*将“匹配”空白,但它不会匹配任何内容。但是,使用\s+可以捕获所有的空格,包括换行符。然而,并非每次你都需要这么做。如果你只想捕获换行符,那么我强烈建议使用\r?\n。如果你想匹配任何空格,那么一定要使用\s类。 - briantist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接