正则表达式贪婪

时间:2014-07-29 21:26:41

标签: regex perl

我有一个perl正则表达式,我相当肯定应该工作(perl)但是太贪心了:

正则表达式: (?:.*serial[^\d]+?(\d+).*)

测试字符串: APPLICATIONSERIALNO123456Plnsn123456te20140728tdrnserialnun12hou

所需的第1组比赛: 123456

实际组1匹配: 12

我已经尝试了前瞻,背后和懒惰的每一种排列,我无法让这该死的事情发挥作用。

我错过了什么。

谢谢!

2 个答案:

答案 0 :(得分:4)

问题不是贪婪,而是案例敏感性

目前,您的正则表达式与12末尾的serialnun12匹配,可能是因为它区分大小写。我们有两个选择:使用大写,或使模式不区分大小写。

选项1:使用大写

如果想要123456,您可以使用:

SERIALNO\K\d+

\K告诉引擎放弃与其返回的最终匹配相匹配的内容。

如果要匹配整个字符串并将123456捕获到组1,请使用:

.*?SERIAL\D+(\d+).*

选项2:在使用(?i)内嵌或i标记

时使用案例敏感度

要仅匹配123456,您可以使用:

(?i)serial\D+\K\d+

请注意,如果您使用g标记,则会匹配这两个数字。

如果要匹配整个字符串并将123456捕获到组1,请使用:

(?i).*?serial\D+(\d+).*

一些提示

  • 您可以使用(?i)内联修饰符或模式末尾的i标记来区分不区分大小写:/serial\D+\K\d+/i
  • 使用[^\d]
  • 而不是\D
  • \D+\d+之类的内容中不需要延迟量词,因为这两个令牌是相互排斥的:\D不会超过\d

答案 1 :(得分:3)

问题不是贪婪;它区分大小写。

目前,您的正则表达式与12末尾的serialnun12匹配,因为这些是serial后的唯一数字。您想要关注SERIALSs是不同的字符。

有两种解决方案。

  1. 使用模式中的大写字符。

    my ($serial) = $string =~ /SERIAL\D*(\d+)/;
    
  2. 使用不区分大小写的匹配。

    my ($serial) = $string =~ /serial\D*(\d+)/i;
    

    可能没有必要这样做,但我想我会提到它以防万一。

相关问题