在匹配行的最后一次出现后附加文本

时间:2016-06-13 02:32:35

标签: ubuntu sed

我有一个生成一些源代码的工具。不幸的是,该工具会从源代码中跳过using子句。

使用像sed这样的实用程序,如何在源文件中插入诸如

之类的行
using namespace xyz;

只出现一次,在最后一行之后才能包含#include?

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();

3 个答案:

答案 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会在该行后添加一个空白行和您的行,并在原地编辑该文件。