我有一个文件,其中包含一些文本和 - 在一行上 - 一个指示应在何处添加新内容的标记
foo
bar
%SUBSTITUTE%
foo
行行替代应替换为新的多行字符串text="some text"
(请注意,我不知道该字符串,例如它可能是读取文件 cat“file”`` 的结果text=
)。替换的结果应为
foo
bar
some text
%SUBSTITUTE%
foo
我有一个工作版本,基于perl
该版本停止工作(显然是由于 perl 版本更改)。现在我正在尝试使用tr
和等标准实用程序sed
来替换该线路。我遇到了一些麻烦,因为要粘贴的字符串可能包含任意字符,包括反斜杠等。我不想在粘贴之前转义这些字符。
有没有一种使用标准工具的安全方法?我发现的该问题的其他问题是已知要粘贴的文本的特定解决方案。
答案1
如果您有 GNU 版本的 sed,您应该能够使用该r
命令从文件中读取并插入新内容,然后删除标记行,例如
sed '/%SUBSTITUTE%/{
r path/to/newcontent
d
}' file
如果您想保留%SUBSTITUTE%
标记后插入,这很棘手,因为无论你做什么,GNUr
扩展都会将文件内容排队,直到结尾当前模式周期的(保留它前只需删除该d
命令即可)。可能最简单的方法是将其附加到文件中newcontent
:您可以像这样即时执行此操作
sed '/%SUBSTITUTE%/{
r /dev/stdin
d
}' file < <(sed '$a %SUBSTITUTE%' path/to/newcontent)
采用完全不同的方法,您可以拆分第一个文件%SUBSTITUTE%
,然后添加新内容
csplit -s file '/%SUBSTITUTE%/'
cat xx00 newcontent xx01
您还可以read
对第一个文件的行执行 bash 循环,并在匹配标记字符串时捕获新的内容文件 - 然而,我已经因为在这个论坛上建议读取循环进行文本处理而感到紧张。不幸的是,两者都没有提供就地解决方案。
答案2
这是另一种使用方法ed
。在标记之前
插入 的全部内容(即在包含 的行之前):FILE
%SUBSTITUTE%
ed -s originalfile <<< $'/%SUBSTITUTE%/- r FILE\nw\nq'
其中:
/%SUBSTITUTE%/
: 在第一行匹配处设置地址%SUBSTITUTE%
-
或: 在: : 写入-1
之前偏移地址一行(替换为仅打印内容而不是写入): 退出编辑器
r FILE
Reads FILE to after the addressed line.
w
originalfile
,p
q
替换FILE
为将在标记之前!echo "$TEXT"
插入 的内容:$TEXT
export TEXT
ed -s originalfile <<'IN'
/%SUBSTITUTE%/-1 r !echo "$TEXT"
w
q
IN
答案3
我基于以下找到了解决方案awk
:
text=`cat "filepaste"`
export text;
<"$file" awk '
BEGIN {REPLACE=ENVIRON["text"] "\n%SUBSTITUTE%" }
{gsub(/^%SUBSTITUTE%$/, REPLACE); print}
'
这里“filepaste”包含要替换的内容%SUBSTITUTE%
。一个优点是可以使用不同的 shell 工具对该字符串进行操作,而无需将其保存回文件。从环境变量中读取awk
变量REPLACE
可以避免扩展 中的转义字符text
。
答案4
既然您有 Perl 解决方案,那么这里还有另一个。我用来rep.txt
存储替换:
$ perl -pe '$re=`cat rep.txt`; chomp($re); s/%SUBSTITUTE%\n/$re/' file.txt
foo
bar
multi
line
string
foo
读取目标文件的每一行 ( file.txt
),然后将给定的脚本应用-e
到它并打印 ( -p
)。