我有一个生成一些源代码的工具。不幸的是,该工具会从源代码中跳过using子句。
使用像sed这样的实用程序,如何在源文件中插入诸如
之类的行using namespace xyz;
只出现一次,在最后一行之后才能包含#include? p>
e.g。
#include <string.h>
#include <stdio.h>
// some functions
void blabla();
会变成:
#include <string.h>
#include <stdio.h>
using namespace xyz;
// some functions
void blabla();
答案 0 :(得分:3)
sed用于单个行上的简单替换,即全部。对于其他任何你应该使用awk:
$ awk 'NR==FNR{if (/#include/) nr=NR; next} {print; if(nr==FNR) print "\nusing namespace xyz;"}' file file
#include <string.h>
#include <stdio.h>
using namespace xyz;
// some functions
void blabla();
以上是使用2次传递 - 第一次查找文件中出现#include
最后一次出现的行号,并将其行号存储在名为nr
的变量中,然后将第2行存储到在第二次传球时击中该线号时,打印“使用...”。如果您希望在参数列表数组中复制文件名,则可以通过将awk 'script' file file
更改为awk 'BEGIN{ARGV[ARGC]=ARGV[1]; ARGC++} script' file
而不指定文件名两次来执行此操作。
或者,如果文件不是很大,你可以将它全部读入内存,然后进行替换,将整个文件视为单个字符串,例如:使用GNU awk进行多字符RS和gensub():
$ awk -vRS='^$' -voORS= '{print gensub(/(.*#include[^\n]+\n)/,"\\1\nusing namespace xyz;\n",1)}' file
#include <string.h>
#include <stdio.h>
using namespace xyz;
// some functions
void blabla();
使用其他awks,你会逐行将字符串逐行构建到变量中,然后使用match()和substr()处理END部分:
$ awk -v ORS= '{rec = rec $0 RS} END{ if (match(rec,/.*#include[^\n]+\n/)) rec = substr(rec,1,RSTART+RLENGTH-1) "\nusing namespace xyz;\n" substr(rec,RSTART+RLENGTH); print rec}' file
#include <string.h>
#include <stdio.h>
using namespace xyz;
// some functions
void blabla();
答案 1 :(得分:0)
这可能适合你(GNU sed):
sed '1h;1!H;$!d;x;/.*#include[^\n]*\n/s//&\ninsert a line here\n/' file
将文件粘贴到内存中并使用greed查找带有所需字符串的最后一行,然后插入所需的字符串。
答案 2 :(得分:0)
将问题分解为简单的步骤:找到#include
的行,找到这些行的最后一行,在该行附加额外的行。
lno=$( sed <file -n '/^#include/=' | sed -n '$p' )
sed -i file -e "$lno"'a\
\
using namespace xyz;
'
这会将bash变量lno
设置为最后一个行号(由sed =
打印)。
最后一个sed
会在该行后添加一个空白行和您的行,并在原地编辑该文件。