Perl正则表达式多行零或更多出现

时间:2011-03-23 00:19:38

标签: regex 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标记为零次或多次,并且没有任何内容被选中。

2 个答案:

答案 0 :(得分: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(这是why you shouldn't try to parse HTML with a regex的更简单版本)。你可以用一些邪恶强迫它为这个简单的情况工作,但是为了舒适,它仍然与Old Ones相当接近。最好的情况是使用真正的解析器。

或者你可以避免重新发明轮子并使用unifdef

答案 1 :(得分:0)

没有尝试过,但这种模式应该是诀窍:

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

请注意,这不会检查任何#elif(您可以将其包含在#else部分中)。