用其他文件的内容替换文件中的模式

用其他文件的内容替换文件中的模式

我有一个文本文件 ( devel.xml)。

我向其中添加了 REPLACETHIS 一词,以便用不同文件 ( temp.txt) 中的内容替换该字符串。

我最接近的是:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

这会在字符串后面插入内容,然后删除该字符串。

这是最好的方法吗?

答案1

您所做的就是删除SUBSTITUTETHIS它出现在文件中的任何位置(但不删除它出现的行的其余部分)并插入temp.TXT该行下方的内容。如果SUBSTITUTETHIS在一行中出现多次,则仅删除第一个出现的位置,并且仅temp.TXT添加 的一个副本。

如果要在SUBSTITUTETHIS出现时替换整行,请使用该d命令。由于您需要同时运行两者r,并且d当有匹配时,请将它们放入支撑组中。

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

某些 sed 实现允许您使用分号来分隔命令并完全省略大括号周围的分隔符,但您仍然需要换行符来终止命令的参数r

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

如果想SUBSTITUTETHIS按文件内容替换,但保留其前后的内容就行,那就比较复杂了。最简单的方法是在 sed 命令中包含文件的内容;请注意,您必须正确引用其内容。

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

或者使用 Perl。这很短,但cat每次替换都会运行一次:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

要在脚本启动时读取一次文件,并避免依赖 shell 命令:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

(为了便于阅读,以两行显示,但您可以省略换行符)。如果文件名是可变的,为了避免引用问题,请通过环境变量将其传递给脚本:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

答案2

sed 's/<\!--insert \(.*\.html\) content here-->/&/;s//\ncat "\1"/e'

或者来自 @KlaxSmashing 的更简洁且(我怀疑)更有效的改进:

sed 's/<\!--insert \(.*\.html\) content here-->/\ncat "\1"/e'

这是我制作的一个单行模板系统,用于将 html 部分插入到另一个 html 文件中。它允许您在模式中指定文件名。然后,该模式将替换为该模式中指定的文件名中的内容。

例如,该行<!--insert somehtmlfile.html content here-->被替换为 的内容somehtmlfile.html。它似乎工作正常,无需对&或等字符进行任何特殊处理\

$ cat first.html
first line of first.html
second line of first.html

$ cat second.html
this is second.html
\ slashes /
and ampersand &
and ! exclamation point
end content from second.html

$ cat file\ name\ space.html
the file containing this content has spaces in the name
and it still works with no escaping.

$ cat input
<!--insert first.html content here-->
input line 1
<!--insert first.html content here-->
input line 2
<!--insert second.html content here-->
input line 3
<!--insert file name space.html content here-->

$ sed 's/<\!--insert \(.*\.html\) content here-->/&/;s//\ncat "\1"/e' input
first line of first.html
second line of first.html
input line 1
first line of first.html
second line of first.html
input line 2
this is second.html
\ slashes /
and ampersand &
and ! exclamation point
end content from second.html
input line 3
the file containing this content has spaces in the name
and it still works with no escaping.

$

答案3

使用(以前称为 Perl_6)

~$ raku -pe 'BEGIN my $donor_file = "donor_file.txt".IO.slurp;   \
             s:g/REPLACETHIS/{$donor_file}/;'  recipient_file.txt

这个 Raku 答案使用熟悉的s///替换习惯用法,并-pe使用自动打印(类似 sed)标志。

在第一个语句中,donor_file.txtslurped(一次全部读取)到$donor_file变量中。在第二个陈述中,:g副词告诉s///我们执行:global替换。在替换运算符(替换一半)的右侧,将$donor_file变量括在{…}花括号中会触发插值,插入所需的文本。

https://raku.org

相关内容