2011-03-23 52 views
2

我有以下文字:Perl的正則表達式多零個或多個正好

#ifdef blah 
a 
#else 
b 
#endif 

#ifdef blah 
c 
#endif 

我想創建一個可以用來刪除一個Perl的正則表達式/更換#ifdef blah/#endif和任何他們所包裹和如果它存在,則保留#else之下的任何內容。執行操作後,上面的文字應該是:

b 

我已經試過這樣的事情: perl -i.bak -pe 'BEGIN{undef $/;} s/^#ifdef blah.*(^#else blah(.*))?#endif blah/\2/smg' test.c

然而,他們似乎是標誌着#else如出現零次或多次問題,沒有選擇。

+0

在輸入中是否嵌套了'#ifdef's? – Cameron 2011-03-23 00:36:11

回答

0

沒有嘗試,但住這種模式應招:

$whatever ~= s/#ifdef.*?(?:#else\n(.*?))?#endif/\1/si 

注意,這將不檢查任何#elif(你可以將它包括類似#else部分)。

1

您給出的正則表達式與#ifdef blah(可能是換行符)之後的單個字符匹配,並且立即希望看到^#else。另外,從它的外觀來看,你使用「blah」作爲「任何」的通配符?

s/^ 
    \# \s* ifdef \s+ \w+ \s* \n   # start of ifdef 
    .*? \n        # ignore true case 
    (?: 
    \# \s* else \s* \n     # there's an else leg 
     (.*? \n)       # ...so capture it 
    )?         # or there isn't 
    \# \s* endif \s* \n     # end it 
/defined $1 ? $1 : ''/smgex;   # if we got an else, return it, otherwise do nothing 

注意,正則表達式是去處理嵌套#ifdef s請正確(這是why you shouldn't try to parse HTML with a regex簡化版本)。你可以強迫它爲這種簡單的情況工作,但有些邪惡,但它仍然過於接近老人的安慰。最好的情況是使用真正的解析器。

或者你可以避開重塑車輪並使用unifdef