2013-12-11 156 views
0

我想匹配BEGIN和END之间的空格和换行符。空字符串不匹配。*?

I.E.我有以下文字:

BEGIN 

END 

BEGIN 
    a 
END 

我想写一个正则表达式,将返回两场比赛:“”和“a”。目前,我有这样的:

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

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

END 

BEGIN 
    a 

你看到问题所在:在第一次开始配对与第二端。我希望它与第一个END配对。它看起来像

.*? 

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

+0

我不知道Perl,但我在C#中试过,它工作。 –

+2

'。*?'* does *匹配空字符串:'perl -We'$ _ =“”;打印“匹配”如果/.*?/;'' – ThisSuitIsBlackNot

+0

我得到了和你一样的结果。 '。*?'确实匹配“,但显然仍然很贪婪。 – iamnotmaynard

回答

0

如何:

my $str = "BEGIN 

END 

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

输出:

("", "a") 
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 

尝试一些正如你所看到的,不符合预期的第一件事就是BEGIN\s*。您希望\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

修饰符的个人偏好放在一边,负面lookahead使意图更加明显海事组织,因为你明确不想遇到下一个“BEGIN”或“END”。 – Wiseguy

+0

这就是我所说的,'。*?'不表示意图 - 而你从答案中删除后的否定性预测,确实如此。 – Wiseguy

+0

@Wiseguy,哦,我误读了,对不起。是的,我删除了它,因为我想出了一种替代解决方案,并且使用前视使得它更加复杂。我会读一个提及。 – ikegami

0

继@Wiseguy提示,这是导致问题的贪婪的空白匹配。当我把它们转换成非贪婪,它开始在所有情况下工作,除了一个在字面上BEGIN和END之间没有任何东西:

BEGIN 
END 

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

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