2013-12-11 215 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