2011-03-23 50 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