使用sed命令插入文件内容

11
我想在给定的模式之前插入文件内容。
这是我的代码:
sed -i "" "/pattern/ {
i\\ 
r $scriptPath/adapters/default/permissions.xml"
}" "$manifestFile"

它添加的是文件路径,而不是文件内容。

有什么想法吗?

5个回答

21

如果想在一个模式之前插入文本,需要将模式空间与保持空间互换位置,在读入文件之前进行。例如:

sed "/pattern/ {
         h
         r $scriptPath/adapters/default/permissions.xml
         g
         N
     }" "$manifestFile"

脚本必须使用双引号,否则$scriptPath将不会被扩展。您能否解释一下为什么需要在末尾加上N? - hipe
@hipe r命令只是将读取的内容排队等待插入输出流中,直到循环结束或读取下一行才会实际读取任何内容。如果没有N选项,文件将在模式空间打印后插入,这将使其作为追加而不是插入功能。这非常不直观。 - Todd A. Jacobs
2
似乎 sed 对于 'r' 命令非常挑剔。根据 http://www.linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/sedfaq5_008.html 的说法:“文件名前后的任何其他字符都将被解释为文件名的一部分。”我尝试使用 r someFile.txt #插入...,但它默默地失败了。 - vscharf
3
只要pattern不是在最后一行,这个方法就能正常工作。 - don_crissti
嗨,Todd和@vscharf,我发现"h"和"g"是可以省略的。我写了这个一行代码(https://dev59.com/S2gu5IYBdhLWcg3wj3v5#56182135)。谢谢! - benok

5

只需删掉 i\\

例子:

$ cat 1.txt
abc
pattern
def

$ echo hello > 2.txt

$ sed -i '/pattern/r 2.txt' 1.txt

$ cat 1.txt
abc
pattern
hello
def

3
它插入在模式后面。如何在它之前插入内容? - ridan

3

我尝试了Todd的答案,效果很好,

但我发现"h"和"g"命令是可以省略的。

感谢这个常见问题解答(在@vscharf的评论中发现),Todd的答案可以简化为一行代码。

sed -i -e "/pattern/ {r $file" -e 'N}' $manifestFile

编辑: 如果您需要here-doc版本,请查看this


2
如果匹配在最后一行或连续的行应该匹配,则此方法无效... - Sundeep

1
我用awk得到了类似这样的东西。看起来很丑,但在我的测试中起到了作用:
命令:
cat test.txt | awk '
/pattern/ {
    line = $0;
    while ((getline < "insert.txt") > 0) {print};
    print line;
    next
}
{print}'

test.txt:

$ cat test.txt
some stuff
pattern
some other stuff

insert.txt:

$ cat insert.txt
this is inserted file
this is inserted file

输出:

some stuff
this is inserted file
this is inserted file
pattern
some other stuff

0

CodeGnome的解决方案不适用于模式在最后一行的情况。所以我使用了三个命令。

sed -i '/pattern/ i\
        INSERTION_MARKER
        ' $manifestFile
sed -i '/INSERTION_MARKER/r $scriptPath/adapters/default/permissions.xml' $manifestFile
sed -i 's/INSERTION_MARKER//' $manifestFile

我发现在这种情况下使用vim最为直观:vim "$fileToEdit" <<< ':$-1 r'"$fileToInsert"$'\n:wq' - Sam

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