Perl正则表达式不能匹配带前导零的字符串/Perl命令行中不正确转义带前导零的数字。

4

我已更新此问题,因为在原始问题中,我所追踪的问题实际上是一个完全不同的错误(在这个背景下不太有趣)。但我在测试中犯的第二次错误是其他人可能会遇到的,它提供了一个非常有趣的见解,因此我将其作为一个问题留在这里。

我试图追踪正则表达式似乎由于前导零而无法匹配的问题。我发现我的命令行测试中所有以下正则表达式都没有匹配成功:

"005630" =~ /^0056(10|11|15|20|21|25|30|31)$/
"005630" =~ /0056(10|11|15|20|21|25|30|31)/  
"005630" =~ /56(10|11|15|20|21|25|30|31)/
"005630" =~ /..56(10|11|15|20|21|25|30|31)/
"005630" =~ /..5630/
"005630" =~ /005630/
"005630" =~ /^005630$/
"005630" =~ /5630/
"005630" =~ /(0)*5630/
"005630" =~ /5630/g
"005630" =~ m/5630/g

这里是匹配的部分:

"x005630" =~ /0056(10|11|15|20|21|25|30|31)/

对于其他情况也是类似的,即一旦添加了一个前导字母,它就可以工作。

测试代码为(在Cygwin bash上使用Cygwin Perl v5.10.1进行测试):

perl -e "print ( "005630" =~ /0056(10|11|15|20|21|25|30|31)/)"   # does not display a true value
perl -e "print ( "x005630" =~ /0056(10|11|15|20|21|25|30|31)/)"  # displays a true value

很明显,这里的引号使用错误(在使用双引号引用字符串时不能使用未转义的双引号)。但是,我仍然不理解为什么第二行尽管引号使用错误也能正常工作。

注意:这种情况也可能发生在没有正则表达式的其他情况下。


1
所有的都正常运行。请复制并粘贴一些代码,展示您所描述的症状。 - Borodin
1
它们在我的电脑上也都能工作(v5.12.4)。你是如何使用这些匹配的?你能展示一些实际的代码,包括一些上下文吗?另外,试试这个正则表达式:/^0056(?:[12][015]|3[01])$/ - amon
1
在 Perl 5.10.0 和 5.16.2 上对我来说运行良好:perl -le 'print "ok" if "005630" =~ /^0056(10|11|15|20|21|25|30|31)$/' ; $ ok。那一行是从你的问题中复制并粘贴的。所以也许你正在遇到 Perl 5.10.1 中的一个 bug? - Moritz Bunkus
感谢大家迄今为止的所有输入。我发现了一个二次测试错误(请参见上文)。amon的 perl -e 'print ( "005630" =~ /^0056(?:[12][015]|3[01])$/)' 是有效的。 - FelixD
当您使用$_作为正则表达式模式时,可能会遇到字符解释问题。该模式是否包含任何可能被解释为特殊正则表达式字符的内容?请使用\Q$_\E来匹配$_的字面内容。或者更好的方法是,如果您正在进行精确匹配(似乎是这样),只需使用eq进行比较,而不是使用正则表达式。 - dan1111
显示剩余4条评论
1个回答

10
给出命令的原因
perl -e "print ( "005630" =~ /0056(10|11|15|20|21|25|30|31)/)"
perl -e "print ( "x005630" =~ /0056(10|11|15|20|21|25|30|31)/)"

只有第二行打印了匹配结果,这是因为Perl支持八进制 数字字面量。正如你所发现的,你的shell正在吃掉引号,所以你实际上执行了以下语句:

print ( 005630 =~ /0056(10|11|15|20|21|25|30|31)/);
print ( x005630 =~ /0056(10|11|15|20|21|25|30|31)/);

任何以零开头且紧随其后不是小数点的数字文字(未加引号的数字)都被视为八进制数。
perl -e "print 005630 . ''"  # prints 2968
perl -e "print x005630 . ''" # prints x005630

在这里需要使用. ''来确保裸字被视为字符串。在你的例子中,=~操作符就是这样做的。

因此,你的正则表达式没有匹配的原因是你的字符串不包含你想要的内容。


1
相当不错的解释 - 在段落中嵌入代码很困难。 - vol7ron
谢谢你,cjm!当我开始看这个问题时,我真应该从文件中编写一个测试脚本的。shell是很危险的;) 八进制数字很有趣,我一定听过。让前导零触发它似乎很危险(我更喜欢像0x等前缀)。也许在我试图调试的脚本中也发生了同样的事情,我会尝试配置八进制值并查看会发生什么。 - FelixD

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