Solaris 10,sed 在第一个#include 语句之前插入#include <iostream>
Solaris 10, sed insert #include <iostream> before first #include statement
在 Solaris 10 上,我有几个类似于 file1.cpp 的源文件,如下所示:
// file1.cpp
#include <string>
#include <unordered_map>
void func() {
. . .
}
我想在第一个 #include
(如果有)之前插入 #include <iostream>
:因此,文件将变为:
// 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$$
但这不符合我的要求,请建议。
这在 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 行(想要的)之前以及第 1 行之后以 #include
开头的第一行之前插入 #include <iostream>
。使用 GNU sed
,您可以使用 0
代替 1
,并且效果很好;引用第 0 行不是 POSIX 标准功能,但可能不适用于 Solaris。
我不确定没有它最好的解决方法是什么——可能使用 awk
而不是 sed
是最简单的(并且它在第一个 #include
之后效果很好当然,第一行也是——这是一个更通用的解决方案):
awk '/^[:space:]*#[:space:]*include/ { if (done++ == 0)
print "#include <iostream>" }
{print}' …filename…
What about if I want to have iostream
as variable captured in $NM
, i.e. NM=iostream
set earlier in the script? How do I use $NM
within the awk
?
NM="iostream"
awk -v header="$NM" \
'/^[:space:]*#[:space:]*include/ { if (done++ == 0)
printf "#include <%s>\n", header }
{print}' …filename…
重点是在命令行中使用-v variable=value
将header名称中继到awk
脚本,然后将print
修改为printf
正确格式化字符串(记住需要换行符)。
在 Solaris 10 上,我有几个类似于 file1.cpp 的源文件,如下所示:
// file1.cpp
#include <string>
#include <unordered_map>
void func() {
. . .
}
我想在第一个 #include
(如果有)之前插入 #include <iostream>
:因此,文件将变为:
// 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$$
但这不符合我的要求,请建议。
这在 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 行(想要的)之前以及第 1 行之后以 #include
开头的第一行之前插入 #include <iostream>
。使用 GNU sed
,您可以使用 0
代替 1
,并且效果很好;引用第 0 行不是 POSIX 标准功能,但可能不适用于 Solaris。
我不确定没有它最好的解决方法是什么——可能使用 awk
而不是 sed
是最简单的(并且它在第一个 #include
之后效果很好当然,第一行也是——这是一个更通用的解决方案):
awk '/^[:space:]*#[:space:]*include/ { if (done++ == 0)
print "#include <iostream>" }
{print}' …filename…
What about if I want to have
iostream
as variable captured in$NM
, i.e.NM=iostream
set earlier in the script? How do I use$NM
within theawk
?
NM="iostream"
awk -v header="$NM" \
'/^[:space:]*#[:space:]*include/ { if (done++ == 0)
printf "#include <%s>\n", header }
{print}' …filename…
重点是在命令行中使用-v variable=value
将header名称中继到awk
脚本,然后将print
修改为printf
正确格式化字符串(记住需要换行符)。