我有以下文字:
#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 :(得分: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
部分中)。