PowerShell正则表达式(八)贪婪与非贪婪匹配 6


根据正则表达式的规则,读者可能会怀疑在上一篇匹配HTML标签时,使用的事“.*?”而不是简单的“.*”。毕竟“.*”已经可以匹配足够的字符了。“.*”和“.*?”之间的不同并不容易识别。下面通过一个例子来澄清。

假设你要再一个长文件中匹配英文月份,但是月份并不是以同样的方式出现的。有时使用短格式,有时使用长格式。正如接下来看见的一样,正则表达式完成可以做到。因为正则表达式支持子表达式以可选的形式出现。

"Feb" -match "Feb(ruary)?"
#True
$matches[0]
#Feb
"February" -match "Feb(ruary)?"
#True
$matches[0]
#February

上面两种情况正则表达式都能识别月份,但是返回的结果却不相同,一个是Feb,一个是February。默认,正则表达式属于“贪婪”模式。在搜索到Feb后会继续贪婪地搜索更多符合模式的的字符。如果可以整个文本会返回。
然后,如果你主要关心的只是规范的月份名称,你可能更喜欢获取缩写的月份名称。这也正是“??”限定符做的,它会将正则表达式转换成“非贪婪”模式,一旦他识别到一个模式,就会立即返回,不再会检查可选的子表达式是否匹配。

"Feb" -match "Feb(ruary)??"
#True
$matches[0]
#Feb
"February" -match "Feb(ruary)??"
#True
$matches[0]
#Feb

到底限定符“??”和之前的例子中的限定符“*?”有什么联系呢?事实上“*?”不是一个独立量词。它会将“贪婪”模式转换成“非贪婪”模式。这就意味着,你可以使用“?”强制将限定符“*”转换成非贪婪模式,尽可能返回短结果。这也正是之前在匹配HTML标签时所做的。接下来你会看到假如没有“非贪婪”模式,正则表达式会尽可能检索更多的内容,也自然会出错。

# 贪婪限定符 * 会尽可能多的匹配结果:
"Contents" -match "<body\b[^>]*>(.*)"
#True
$matches[1]
#Contents<\body>
#非贪婪限定符*?, 尽可能短的返回匹配结果
"Contents" -match "<body\b[^>]*>(.*?)"
#True
$matches[1]
#Contents

根据正则表达式中的定义,HTML标签中可以匹配任意字符,而且必须以””作结,贪婪限定符会跨过第一次出现的继续匹配。但是非贪婪限定符则会在第一次匹配到结束。

本文链接: https://www.pstips.net/regex-lazy-and-greedy-match.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

回复 ryan 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

6 条评论 “PowerShell正则表达式(八)贪婪与非贪婪匹配