加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

正则表达式 – Perl正则表达式引擎错误?

发布时间:2020-12-14 05:37:54 所属栏目:百科 来源:网络整理
导读:我一直在尝试编写一个正则表达式来验证文件,以确保它遵循特定的格式.该文件应该有一个版本();行后面跟一个或多个元素();块. 以下是有效文件的示例: version(1.0);element();element();element(); 作为测试,我创建了以下Perl示例: use strict;use warnings;
我一直在尝试编写一个正则表达式来验证文件,以确保它遵循特定的格式.该文件应该有一个版本();行后面跟一个或多个元素();块.

以下是有效文件的示例:

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>
        As*(?&version)s*
        (?: (?&element) s* )+
        s*Z
    )
    (?<version>
        version(.+?);
    )
    (?<element>
        elements*
        (?&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

解决方法

非贪婪的比赛一旦满足就不会停止.它试图尽快继续.如果正则表达式的其余部分无法匹配,则仍会发生回溯 – 但对于非贪婪的量词,回溯意味着匹配更多.

避免这种情况的一种可能性在于回溯控制.例如,您可能希望在版本最初匹配后禁止回溯.我们可以通过(?> …)构造来做到这一点.这与外部模式独??立地匹配包含的模式.如果模式的其余部分失败,则回溯将不会继续进入包含的模式,但会跳过整个包含的模式.描述这个有点困难,详情请见perldoc perlre.

添加到量词(例如,?,*)具有与(?> …)类似的效果.在有效的正则表达式中,优选这些无回溯量词和(?> …)组是非常可取的.

具体来说,替换

(?<valid_text>
    As*(?&version)s*
    (?: (?&element) s* )+
    s*Z
)

(?<valid_text>
    As*(?>(?&version))s*
    (?: (?&element) s* )++
    s*Z
)

作为另一种选择,您可以使用(* PRUNE)回溯控制动词.遇到PRUNE命令后,不会发生超过该点的回溯.这使得匹配到目前为止所选择的替代方案.

(?<valid_text>
    As*(?&version)s* (*PRUNE)
    (?: (?&element) s* )+
    s*Z
)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读