我需要删除围绕某一行的模式:
#undef LZZ_INLINE
#ifdef LZZ_ENABLE_INLINE
#include "somename.inl"
#endif
应该变成:
#include "somename.inl"
我不知道somename
提前。如何以通用方式使用例如 sed 或 awk 来做到这一点?
如果文件大小允许读取一次将其全部加载到内存中,您可以这样做
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
如果一切顺利,请删除文件:)
请尝试此 oneliner 是否适合您:
awk '/#undef LZZ_INLINE/{next;} /#ifdef LZZ_ENABLE_INLINE/{x=1;next;}x&&/#endif/{x=0;next;}1' file
将此添加到名为 fix.sed 的文件中
/^#undef LZZ_INLINE/{
N
N
N
s/.*\(#include "[^"]*"\).*/\1/
}
像这样运行:
sed -f fix.sed 你的原始文件
假设@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 循环都是风格或取决于您的操作系统提供的内容。