空字符串不匹配。*?

时间:2013-12-11 16:18:17

标签: regex perl

我希望匹配BEGIN和END之间关于空格和换行符的任何内容。

即。我有以下文字:

BEGIN

END

BEGIN
   a
END

我想要写一个可以返回两个匹配的正则表达式:''并且' a'。目前我有这个:

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

然而,这个只给出一个匹配:

END

BEGIN
    a

您会看到问题所在:第一个BEGIN与第二个END配对。我希望它与第一个END配对。它看起来像

.*? 

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

4 个答案:

答案 0 :(得分:8)

 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

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

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

如您所见,非贪婪修饰符在用于避免匹配某些内容时容易失败。如果你想要更强大的东西,你可以使用以下习语:

(?:(?!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

答案 1 :(得分:0)

怎么样:

my $str = "BEGIN

END

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

<强>输出:

("", "a")

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

在@Wiseguy的暗示之后,贪婪的空白匹配导致了这个问题。当我将它们转换为非贪婪时,它开始在所有情况下工作,除了在BEGIN和END之间几乎没有任何东西:

BEGIN
END

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

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