使用Sed将文件内容替换为模式

4

我希望使用sed(我想?)将一个模式替换为文件内容。

例子

文件1(主文件)

Hello <<CODE>>
Goodbye.

文件2(内容)

Anonymous person,
I am very nice. 

文件3(目标)

Hello Anonymous person,
I am very nice.
Goodbye.

现在,我正在使用这个命令:

sed "/<<CODE>>/{r file2
:a;n;ba}" file1            | \
    sed "s/<<CODE>>//g"    > \
    file3

但是这将输出:
Hello
Anonymous person,
I am very nice.
Goodbye.

(注意在Hello后的换行符)

  • 我该如何做到没有这个换行符呢?
    • (请注意,file2中可能包含各种字符:括号、换行符、引号等等)

必须使用 sed 吗?你可以使用 perlruby 或者 python 吗? - mr rogers
脚本的其余部分是用bash编写的,因此任何不需要调用/创建新的(脚本)文件的内容都会受到赞赏。 - Etienne Bruines
但是一个Perl或Ruby的单行命令也可以运行,对吧? - mr rogers
如果你知道如何编写,那么是的 :-)。我对 perl / ruby 的了解有限。 - Etienne Bruines
1
我还在思考。我不确定Perl/Ruby哪个更好,但它似乎可能会打开一些东西。 - mr rogers
5个回答

3

使用awk更加简单:

awk 'FNR==NR{s=(!s)?$0:s RS $0;next} /<<CODE>>/{sub(/<<CODE>>/, s)} 1' file2 file1
Hello Anonymous person,
I am very nice.
Goodbye.

解释:

  • FNR==NR - 对于输入中的第一个文件(即file2),执行此块
  • s=(!s)?$0:s RS $0 - 将整个文件内容连接成字符串s
  • next - 读取下一行,直到在第一个文件上达到EOF
  • /<<CODE>>/ - 如果找到包含<<CODE>>的行,则执行该块
  • sub(/<<CODE>>/, s) - 将<<CODE>>替换为字符串s(即file2的数据)
  • 1 - 输出结果

编辑:非正则表达式方法:

awk 'FNR==NR{s=(!s)?$0:s RS $0; next}
     i=index($0, "<<CODE>>"){$0=substr($0, 1, i-1) s substr($0, i+8)} 1' file2 file1

1
我认为你和我对“简单”的定义不同 ;-). 不过,它仍然完美地工作。 - Etienne Bruines
1
@EtienneBruines:哈哈 :) 希望我的解释能让我们的定义更接近。如有任何问题,请随时提出以便进一步解释。 - anubhava
这会在使用&字符时中断(即:&字符被替换为<<CODE>>)。 - Etienne Bruines
刚刚发现 sed 命令需要转义 & 字符。或许这就是原因。 - Etienne Bruines

1

Perl中还不错:

 cat file1 | perl -e "open FH, qq(file2); \$f2=join '', <FH>; chomp \$f2; map {s/<<CODE>>/\$f2/g; print \$_} <STDIN>" > file3

(也许我不是最好的Perl编程人员)

很简单,将整个file2读入,进行替换,然后打印输出。


1
您可以简单地使用以下代码实现:

awk '{gsub("<<CODE>>", filetwo)}1' filetwo="$(<file2)" file1

1

awk虽然可能更难读懂,但可能是正确的方法。

只是为了比较起见,这里有一个ruby版本。

ruby -ne 'BEGIN{@body=File.open("file2").read}; puts gsub(/<<CODE>>/,@body);' < file1

0

我正在考虑一种解决方案,其中我们使用Bash来评估单引号分隔sed脚本之外的cat过程,但不幸的是,如果你的file2包含换行符,以下内容将无法正常工作:

sed 's/<<CODE>>/'"$(cat file2)"'/' file1

它接受file2中的空格,但不接受换行符,正如您在下面这段代码中看到的那样,无论file2的内容是什么,它都能正常工作:

sed 's/<<CODE>>/'"$(cat file2 | tr -d '\n')"'/' file1

但是,显然,在引用之前修改文件的内容是不好的。:-(

如果您想尝试,可以首先使用tr将换行符转换为某些奇怪的不可预期的字符,然后在 sed 运行其脚本后将其翻译回来:

sed 's/<<CODE>>/'"$(cat file2 | tr '\n' '\3')"'/' file1 | tr '\3' '\n'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接