【发布时间】:2017-09-21 21:27:19
【问题描述】:
我一直在尝试编写正则表达式来验证文件以确保它遵循特定格式。该文件应该有一个version(); 行,然后是一个或多个element(); 块。
下面是一个有效文件的例子:
version(1.0);
element
(
);
element
(
);
element
(
);
作为测试,我创建了以下 Perl 示例:
use strict;
use warnings;
my $text = <<'END_TEXT';
version(1.0);
element
(
);
garbage <--- THIS SHOULD NOT MATCH!
element
(
);
element
(
);
END_TEXT
my $rx_defs = qr{(?(DEFINE)
(?<valid_text>
\A\s*(?&version)\s*
(?: (?&element) \s* )+
\s*\Z
)
(?<version>
version\(.+?\);
)
(?<element>
element\s*
(?&element_body);
)
(?<element_body>
\( (?: [^()]++ | (?&element_body) )* \)
)
)}xms;
if ($text =~ m/(?&valid_text)$rx_defs/) {
print "match";
}
如您所见,文本中有一行“垃圾”应该使其无效,但由于某种原因,Perl 似乎仍然认为该文本是有效的!当我运行此代码时,它会产生输出:
match
我花了好几个小时试图找出我的正则表达式出了什么问题,但我就是没发现。我什至使用online regular expression tester 测试了确切的正则表达式,根据测试我的正则表达式应该可以正常工作! (如果您想在格式有效时查看它是否正确匹配,请尝试删除“垃圾”行。)
这让我一整天都被难住了,让我想知道 Perl 正则表达式引擎本身是否存在错误。有人可以告诉我为什么这是不应该匹配的吗?
我正在使用 perl v5.20.1
【问题讨论】:
-
这一点看起来很可疑:
version\(.+?\);- 括号可能包括一个元素和垃圾。考虑限制内容,例如到[^)]+。 -
这似乎可以解决它...但是如何解决?非贪婪匹配应在满足后立即停止!
-
为什么这会在 perl 中匹配,但在使用“PCRE”作为正则表达式类型的正则表达式测试网站上却不匹配?它们的功能应该相同,不是吗?
-
一个非常酷的正则表达式,毫无疑问,正则表达式是一个很棒的工具,毫无疑问......但我忍不住说:这很难,但可以通过使用工具来避免处理那些嵌套/平衡的分隔符。 (您上一个问题中this answer 的确切点。)
-
提示:这绝不是引擎/语言/编译器错误;它始终是用户错误。好吧……除非……但那是一长串可能的行为原因列表中的最后一件事。 (我会重新考虑这样的标题;你确定吗?)
标签: regex perl validation debugging pcre