我在我的脚本中有一个正则表达式,我写了好几年了。
我知道这个正则表达式的作用(查找大于80%的百分比),但我不记得它的含义/原理。我看到使用了三元运算符,还有最后一个闭合括号匹配,但是我不知道例如 ??
的含义:
qr/^(\d+)%$(??{$^N>= 80 ? '':'^'})/
有人能为我解释一下这个正则表达式吗?
(??...)
的含义,使用它可能会充满错误。我写了20多年的perl正则表达式,我的自然倾向是将这样的“用例”编码为正则表达式结果的过滤器,而不是直接嵌入perl代码。警示!
好的,让我们分析一下这个正则表达式:^ # start of text
( # begin capture group
\d+ # one or more digits 0-9
) # end of capture group
% # literal percent sign character
$ # end of text
(??{ # start embedded perl code
$^N >= 80 # if last closed match group($^N) is greater than or equal to 80
? '' # then return empty pattern ('')
: '^' # else return start of text (^) pattern
}) # end embedded perl code
$^N
引用最近匹配成功的子字符串,(??{ ... })
零宽断言会执行包含在其中的Perl代码,并将返回值转换为新的正则表达式,这个新的正则表达式将被添加到原始模式中。
因此,在这个例子中,我们匹配一个或多个数字并紧接着一个百分号字符。然后,如果捕获的值大于或等于80,则对文本执行一个空模式(实际上允许整个模式匹配并返回捕获的值),否则,执行 ^
(开始)模式,该模式不能匹配字符串末尾,从而不返回任何内容。
(注意,通过在Perl正则表达式中添加/x修饰符,您可以直接将注释嵌入到模式中,同时忽略嵌入的空格。我发现这是记录复杂正则表达式的好方法。)
$(??{代码})
执行代码
,然后将结果替换到正则表达式中。其中,$^N
会被替换成最近捕获组匹配的内容,此处为(\d+)
。带有此替换的正则表达式再次进行匹配。
因此,如果字符串以一个数字和%
开头,^(\d+)%
会匹配它。然后执行$^N >= 80 ? '' : '^'
,用数字替换$^N
。如果数字至少是80
,则正则表达式变为^(\d+)%
,整个匹配成功。但如果数字小于80
,则变为^(\d+)%^
。由于第二个^
不能在字符串中间匹配,正则表达式不再匹配。
因此,这个正则表达式匹配以百分数至少为80开头的字符串。
if ( (/^([0-9]+)\s*%/)[0] > 80 )
... - zdim