用任意新文本替换文本文件中的标记

用任意新文本替换文本文件中的标记

我有一个文件,其中包含一些文本和 - 在一行上 - 一个指示应在何处添加新内容的标记

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 FILEReads FILE to after the addressed line.
woriginalfile,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)。

相关内容