在Solaris 10上,我有几个类似于file1.cpp的源文件,如下所示:
// file1.cpp
#include <string>
#include <unordered_map>
void func() {
. . .
}
我想在第一个#include <iostream>
之前插入#include
(如果有的话):因此,该文件将成为:
// file1.cpp
#include <iostream>
#include <string>
#include <unordered_map>
void func() {
. . .
}
如果没有包括例如
// file1.cpp
void func() {
. . .
}
这将成为:
// file1.cpp
#include <iostream>
void func() {
. . .
}
但是,如果文件已包含#include <iostream>
,则会忽略另一个#include <iostream>
的插入。因此,如果我们有,
// file1.cpp
#include <string>
#include <unordered_map>
#include <iostream>
void func() {
. . .
}
它将保持不变,即
// file1.cpp
#include <string>
#include <unordered_map>
#include <iostream>
void func() {
. . .
}
我的尝试:
bash-3.00$ cat TRYIT
#!/bin/bash
echo \#include \<iostream\> > x$$
for i in `find . -type f -name "*.cpp"`
do
if ! grep -s "\#include \<iostream\>" "$i" > /dev/null; then
sed "/\#include/r x$$" "$i" > "$i".bak
mv "$i".bak "$i"
fi
done
rm x$$
但是根据我的要求,这不起作用,请建议。
答案 0 :(得分:2)
这在Linux上运行正常,我相信它应该适用于Solaris。
档案xyz.c
:
/* First line must not start #include */
#include <stdio.h>
#define PERGATORY
#include <meniscus.h>
the real code
命令:
$ sed -e '1,/^[:space:]*#[:space:]*include/ { /^[:space:]*#[:space:]*include/i\
> #include <iostream>
> }' xyz.c
/* First line must not start #include */
#include <iostream>
#include <stdio.h>
#define PERGATORY
#include <meniscus.h>
the real code
$
如果你需要处理在第一行开头有#include
的文件,那就更加狡猾了。如果没有更改,您会在第1行(想要的内容)之前插入#include <iostream>
,也可以在以#include
开头的第1行之后的第一行之前插入sed
。使用GNU 0
,您可以使用1
代替awk
并且效果很好;引用第0行不是POSIX标准功能,但可能不适用于Solaris。
我不确定没有它的最佳解决方法是什么 - 可能使用sed
代替#include
是最难的(并且它适用于第一行之后的第一个awk '/^[:space:]*#[:space:]*include/ { if (done++ == 0)
print "#include <iostream>" }
{print}' …filename…
当然,这也是一个更通用的解决方案):
iostream
如果我希望将
$NM
作为NM=iostream
中捕获的变量,即脚本中先前设置的$NM
怎么办?如何在awk
中使用NM="iostream" awk -v header="$NM" \ '/^[:space:]*#[:space:]*include/ { if (done++ == 0) printf "#include <%s>\n", header } {print}' …filename…
?
-v variable=value
关键是在命令行上使用awk
将标头名称转发到print
脚本,然后将printf
修改为find_host(...)
到正确格式化字符串(记住需要换行符)。