【问题标题】:Empty string doesn't match .*?空字符串不匹配。*?
【发布时间】:2013-12-11 16:18:17
【问题描述】:

我想匹配介于 BEGIN 和 END 之间的任何内容,包括空格和换行符。

I.E.我有以下文字:

BEGIN

END

BEGIN
   a
END

我想编写一个正则表达式,它会返回两个匹配项:'' 和 'a'。目前我有这个:

/\s*BEGIN\s*\n(.*?)\n\s*END\s*\n/sg

但是,这个只给出一个匹配:

END

BEGIN
    a

您知道问题出在哪里:第一个 BEGIN 与第二个 END 配对。我希望它与第一个 END 配对。好像

.*? 

不匹配空字符串 - 即它贪婪匹配。

【问题讨论】:

  • 我不了解 Perl,但我在 C# 中尝试过,它成功了。
  • .*? 确实匹配空字符串:perl -We '$_ = ""; print "match" if /.*?/;'
  • 我得到的结果和你一样。 .*? 确实匹配 "" 但显然仍然很贪婪。
  • .*? 并不贪心,但\s* 是。
  • perl non-greedy problem 的可能重复项

标签: regex perl


【解决方案1】:
 222224466888AA                         Expected
"BEGIN\n\nEND\n\nBEGIN\n   a\nEND\n"
 22222334455555555555555555566888AA     Got

 111 22222 333 44 55555 66 777 888 999 AA    
/\s* BEGIN \s* \n (.*?) \n \s* END \s* \n/xsg

如您所见,与预期不匹配的第一件事是BEGIN 之后的\s*。您希望 \s* 匹配除换行符以外的任何空格,这可以使用 [^\S\n]* 来完成。

/^ [^\S\n]* BEGIN [^\S\n]* \n (.*?) \n [^\S\n]* END [^\S\n]* \n/xsmg

如您所见,non-greediness 修饰符在用于避免匹配某些内容时很容易失败。如果你想要更健壮的东西,你可以使用以下成语:

(?:(?!STRING).)* 是 STRING 就像 [^CHAR]* 是 CHAR

这会给你

/
   ^ [^\S\n]* BEGIN [^\S\n]* \n
   ( (?:(?! ^ [^\S\n]* (?: BEGIN | END ) [^\S\n]* \n ).)* ) \n
   [^\S\n]* END [^\S\n]* \n
/xsmg

【讨论】:

  • 除了个人偏好的修饰符之外,负前瞻使 IMO 的意图更加明显,因为您明确不希望遇到下一个“BEGIN”或“END”。
  • 这就是我要说的,.*? 没有表现出意图——而你已经从你的答案中删除的否定前瞻却有。
  • @Wiseguy,哦,我看错了,对不起。是的,我删除了它,因为我想出了一个替代解决方案,而使用前瞻只是让它变得更加复杂。我会读一提。
  • 表示发生的事情的好方法
【解决方案2】:

怎么样:

my $str = "BEGIN

END

BEGIN
   a
END";
my $re = qr~BEGIN\s+(.*?)\s+END~;
my (@m) = $str =~ /$re/sg;
dump@m;

输出:

("", "a")

【讨论】:

    【解决方案3】:

    我找到了这个网站,它似乎描述了您的问题:

    http://www.regular-expressions.info/dot.html

    根据该页面上的信息,我建议尝试类似BEGIN\n?([^\r\n])\n?END

    【讨论】:

      【解决方案4】:

      根据@Wiseguy 的提示,导致问题的是贪婪的空白匹配。当我将它们转换为非贪婪时,它开始在所有情况下工作,除了在 BEGIN 和 END 之间实际上什么都没有的情况:

      BEGIN
      END
      

      我通过添加一个非捕获组来解决它:

      /BEGIN\s*\n(?:(.*?)\n)??\s*END\s*\n/sg
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-26
        • 1970-01-01
        • 1970-01-01
        • 2022-11-28
        • 2011-05-20
        • 2015-05-04
        • 1970-01-01
        相关资源
        最近更新 更多