2

我需要删除围绕某一行的模式:

#undef LZZ_INLINE
#ifdef LZZ_ENABLE_INLINE
#include "somename.inl"
#endif

应该变成:

#include "somename.inl"

我不知道somename提前。如何以通用方式使用例如 sed 或 awk 来做到这一点?

4

4 回答 4

3

如果文件大小允许读取一次将其全部加载到内存中,您可以这样做

sed -i.bk ':a;$!{N;ba}; s/#undef LZZ_INLINE\n#ifdef LZZ_ENABLE_INLINE\n\(#include [^\n]*\)\n#endif/\1/g' input.file

.bk如果一切顺利,请删除文件:)

于 2012-12-17T12:45:05.007 回答
2

请尝试此 oneliner 是否适合您:

awk '/#undef LZZ_INLINE/{next;} /#ifdef LZZ_ENABLE_INLINE/{x=1;next;}x&&/#endif/{x=0;next;}1' file
于 2012-12-17T12:49:14.253 回答
2

将此添加到名为 fix.sed 的文件中

/^#undef LZZ_INLINE/{
N
N
N
s/.*\(#include "[^"]*"\).*/\1/
}

像这样运行:

sed -f fix.sed 你的原始文件

于 2012-12-17T13:03:37.287 回答
2

假设@glennjackman 发布了答案:

awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} 1' file

是正确的,您只想就地更新输入文件,这是使用 awk 执行此操作的一种方法:

awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {out[++nr]=$0} END{close(FILENAME); for (i=1;i<=nr;i++) print out > FILENAME}' file

(即替换1{out[++nr]=$0} END{close(FILENAME); for (i=1;i<=nr;i++) print out > FILENAME}

这是另一个:

awk '/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {print > "/tmp/\""FILENAME"\"" } END{system("mv /tmp/\""FILENAME"\" \""FILENAME"\""}' file

(即替换1{print > "/tmp/\""FILENAME"\"" } END{system("mv /tmp/\""FILENAME"\" \""FILENAME"\""}

如何实现它有一些变化,但基本思想只是缓冲输出,直到您完成读取输入文件然后覆盖输入文件。NBD 无论如何...

我应该提到的另一个变体是创建一个 tmp INPUT 文件,它看起来像这样:

awk '
BEGIN{
   tmp="/tmp/\"" ARGV[1] "\""
   while ( (getline var < ARGV[1]) > 0 ) {
      print var > tmp
   }
   close(tmp)
   out = ARGV[1]
   ARGV[1] = tmp
}
/#undef LZZ_INLINE/{next} /#ifdef LZZ_ENABLE_INLINE/{x=1;next}x&&/#endif/{x=0;next} {print > out}' file

无论您使用 system("mv...") 还是 getline 循环都是风格或取决于您的操作系统提供的内容。

于 2012-12-17T14:45:46.263 回答