最近朋友有一个需求,要整理头文件中的include逻辑,需要在最后一个include后面再新增一行include,这里有两种实现方案:
1.awk实现
#!/usr/bin/awk -f
BEGIN{
last=0
}
{
if(match($1,"//")>0)
{
print $0;
next
}
if(last==0 && match($1,"^#include")>0)
{
last=0
}
else
{
if(last==0)
{
last=1;
print "#include <new.h>";
}
}
print $0;
}
这里忽略了注释行,会在第一次遇到不是"#include"的行前面插入新的include,算是基本完成任务吧
2.sed实现
相当精巧
sed '1h;1!H;$!d;x;s/.*#include[^\n]*/&\n#include <new.h>/'
具体执行过程是这样的:
1h表示把第一行放到hold
1!H表示除了第一行之外都append到hold
$!d表示除最后一行外,执行d(意味着后面的x;s...是不执行的)
x表示把hold交换到pattern,
s就是在pattern执行替换,这里正则可以匹配最后一个,是最小匹配,
所以前面那些指令就是为了执行一个str=str+line,但是不执行替换,只在文件的最末尾执行替换
这里的关键就是那个最小匹配的正则,.*#include[^\n]* , 匹配最后一次出现的 include语句,同时替换字段里的&表示前面的匹配项,比如最后一行匹配是 "#include <iostream>",那么替换项&\n#include <new.h> 就是 "#include <iostream>\n#include <new.h>",相当于在最后一次匹配项之后追加了一句
备注:
第一次匹配替换
sed '0,/include/s/.*#include[^\n]*/&\n#include <new.h>/'