我有一个文本文件 ( 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.txt
将slurp
ed(一次全部读取)到$donor_file
变量中。在第二个陈述中,:g
副词告诉s///
我们执行:global
替换。在替换运算符(替换一半)的右侧,将$donor_file
变量括在{…}
花括号中会触发插值,插入所需的文本。