Perl正则表达式(regex)在我设为可选时失败
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl正则表达式(regex)在我设为可选时失败相关的知识,希望对你有一定的参考价值。
我正在Perl 5.22上运行以下代码段:
DB<41> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days).*$/
0 34
以上代码按预期工作,并从“ 34天”中抽出了34天。
我的问题是,通过添加一个使捕获组成为可选的?在它的末尾是这样的:
DB<4> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days)?.*$/
0 undef
为什么它不再匹配34?我已经在网上搜索过,但是找不到与我的匹配的任何问题(如果您有一个解释它的链接,那就太好了)。
感谢您的宝贵时间。
为什么它不再匹配34?
因为.*?
in
"up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days)?.*$/
现在可以一直匹配到字符串的末尾,因为后面的内容可能匹配零次。
正则表达式始终从左到右工作;量词总是首先尝试尽可能多地匹配,或者在不贪心时尽可能少匹配(例如.*?
)。当他们达到不可比拟的状态时,只有这样,他们才会备份并尝试进行新的匹配(回溯)。正则表达式的关键在于正则表达式引擎将首先尝试的方法。
.*?
首先将尝试在字符串的开头匹配空字符串,因为这是它可以匹配的最少字符。对于第一个正则表达式,这不会导致成功的整体匹配,因此最终回溯直到.*?
匹配“ up”,以便随后的组可以匹配“ 34天”。但是,如果将以下组设为可选,则首先尝试将.*?
的初始模式与空字符串匹配,然后将(?:(\d+) days)?
与空字符串匹配(因为它不能与数字匹配,后跟“ days”)特定位置,但可以匹配空字符串),然后是.*
,匹配其余字符串,然后是字符串末尾;成功的比赛。
Regexp::Debugger和https://regex101.com/都可以很好地可视化行为(只是要注意PCRE与Perl regex不完全相同)。
由于.*?
和(?:(\d+) days)?
都匹配空字符串,然后.*$
然后匹配任何其他字符串,即整个输入字符串。
如果您检查以下内容
use strict;
use warnings;
my $s = "up 34 days, 22:04 and more";
if ($s =~ m/.*?(?:(\d+) days)(.*)$/)
print("first:\n $1=\"$1\"\n \$2=\"$2\"\n");
if ($s =~ m/.*?(?:(\d+) days)?(.*)$/)
print("second:\n \$1=\"$1\"\n \$2=\"$2\"\n");
您会得到
first:
34="34"
$2=", 22:04 and more"
second:
$1=""
$2="up 34 days, 22:04 and more"
作为输出(以及有关$1
的未定义警告,您可以在此处忽略这是说明。
以上是关于Perl正则表达式(regex)在我设为可选时失败的主要内容,如果未能解决你的问题,请参考以下文章
将“NSManaged public var”设为可选布尔值
使用 View Controller 作为辅助视图的委托失败,在展开可选时意外发现 nil