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 正确格式化字符串(记住需要换行符)。