多行替换

多行替换

我花了很长时间试图弄清楚这一点。碰巧的是,我不需要再这样做了;我找到了另一种方法。但为了我的理智,我还是想知道答案。

sed用一些文本替换标记非常容易。我不明白的是如何sed插入一个巨大的文本块,具有复杂的格式,如多行、制表符等。你是怎么做到的?是sed最好用还是什么?

答案1

我会用于ex此类任务,除非您确实有数据流。我将ex命令保存在此处的文档中:

ex $FILENAME << END_EX_COMMANDS
" Find the mark, assuming it's an entire line
/^MARKER$/
" Delete the marker line
d
" Add the complex, multi-line text
a
Complex, vividly formatted text here.
Even more "specially" formatted text.
.
" The '.' terminates the a-command. Write out changed file.
w!
q
END_EX_COMMANDS

使用对于用户ex来说是一个优势:他们已经知道命令的击键,尽管它给您带来盲目编辑的感觉。您还可以执行多个添加或全局替换,以及“:”模式下可以执行的任何操作。vivimvim

答案2

如果您要将文本插入到名为 /tmp/insert.txt 的文件中的标记处,则可以按如下方式完成此任务:

sed '/MARKER/ r /tmp/insert.txt' < inputfile

上面的 sed 命令将读取“inputfile”并查找 MARKER。当它找到它时,它将 /tmp/insert.txt 的内容插入到输出流中。

如果您想删除标记本身,请尝试以下操作:

sed '/MARKER/ {s/MARKER//; r /tmp/insert.txt
}' <inputfile

请注意,“}”右大括号前面必须有一个新行。

与第一个命令一样,sed 将在带有 MARKER 的行上运行。它会将 MARKER 替换为空,然后读取 /tmp/insert.txt

答案3

我相信这个命令就是您正在寻找的:

r FILENAME
     As a GNU extension, this command accepts two addresses.

     Queue the contents of FILENAME to be read and inserted into the
     output stream at the end of the current cycle, or when the next
     input line is read.  Note that if FILENAME cannot be read, it is
     treated as if it were an empty file, without any error indication.

     As a GNU `sed' extension, the special value `/dev/stdin' is
     supported for the file name, which reads the contents of the
     standard input.

答案4

如果您希望删除标记本身,请在一行中尝试以下操作:

sed -e '/MARKER/ r /tmp/insert.txt' -e '/MARKER/d' < inputfile

或者

sed -e '/MARKER/ {r /tmp/insert.txt' -e 'd }' < inputfile

相关内容