用多行文件替换行

时间:2018-03-13 21:34:08

标签: bash sed

尝试用多行文件替换行。我可以使用单行文件或多行字符串轻松完成此操作(见下文)。

#!/bin/bash

NEW_STRING="apple\nbanana\ncarrot"

sed -i "3s/.*/$(echo "${NEW_STRING}")/" tmp.txt

# Outputs...
# line 1
# line 2
# apple
# banana
# carrot
# line 4
# line 5
# ...
# etc

但是,当我更改代码以使用多文件(例如replace.txt)时,我收到以下错误:

sed: -e expression #1, char 10: unterminated `s' command

broken_script.bash

#!/bin/bash

FILE=`cat replace.txt`

sed -i "3s/.*/$(echo "${FILE}")/" tmp.txt

replace.txt

++++
++++++++++++++++++++++++++++++++++++++++++++++
  apple size=8, align=2, ..., etc.
  banana size=64, align=8, ..., etc.
  ...
  carrot size=92, align=4, ..., etc.

如果我将broken_script.bash删除为单行(即replace.txt),请注意++++

有谁看到我做错了什么?为什么这不能用多行文件作为替换文本(例如单行文件或多行字符串)?

3 个答案:

答案 0 :(得分:2)

要用文件内容替换行,可以使用r命令:

sed -e 3rreplace.txt -e 3d tmp.txt

正如评论中所述,sed -e 3d -e 3rreplace.txt不起作用,因为d命令在读取下一行后立即返回到程序的顶部,并且从不执​​行r命令。

答案 1 :(得分:1)

首先:放弃echo部分。您可以直接使用该变量。

回到实际问题:
区别在于您如何编码换行符。在您编写\n的第一个命令中,确实表示换行符。 \n不会被' bash'解释,而是直接发送到sed。在第二个命令中,文件内容将发送到sed,包括文字换行符。对于包含line1line2两行的文件,sed看到的命令是

3s/.*/line1
line2/

sed无法处理此类多行命令。

非解决方案:
看起来,您只想将一个文件的第三行替换为另一个文件的内容。这可以通过

完成
cat <(head -n 2 file1) file2 <(tail -n +4 file1)  

head -n2 file1打印file1的前两行 tail -n +4 file 1从第4行开始打印file1的所有行。
<(command)称为流程替换,并模拟包含command输出的文件。
cat连接三个&#34;文件&#34;。

答案 2 :(得分:1)

sed可以通过一些引用杂耍

来做到这一点
$ seq 5 | sed -e '/3/{r replace.txt' -e 'd}'

1
2
++++
++++++++++++++++++++++++++++++++++++++++++++++
  apple size=8, align=2, ..., etc.
  banana size=64, align=8, ..., etc.
  ...
  carrot size=92, align=4, ..., etc.
4
5

为了替换你需要提供文件

$ sed -i -e '/3/{r replace.txt' -e 'd}' file

当然先测试或备份。