我有一个名为“insert.txt”的文件。它看起来像这样(或丑陋):
ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>
我想替换目标文件(target.txt)中的文本块,该文件由“STARTSTACKOVERFLOW”分隔为“STOPSTACKOVERFLOW”。 (我在这里简化了一点问题,但它也是一样的。)
我用来执行此操作的bash脚本是:
TARGETFILE=target.txt
SOURCEFILE=insert.txt
SOURCETXT="$(<$SOURCEFILE)"
DELIMTXT=$(printf "%q" "$SOURCETXT")
sed -i -e "/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/cSTARTSTACKOVERFLOW\n\n${DELIMTXT}\n\nSTOPSTACKOVERFLOW\n" $TARGETFILE
问题是粘贴到“target.txt”的内容实际上是ANSI-C引用的:
$'ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>'
注意$''已添加。
原因是printf“%q”正在产生这种引用风格。我想避免这种情况 - 虽然需要它,因为我必须逃避这个文件中的所有不良。
使用bash和sed是否有更好的方法来执行上述操作?
答案 0 :(得分:0)
POSIX sed有一个'r'命令可以从文件中读取。所以:
sed -i -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/r large.txt' target.txt
唯一的问题是文件是读取一次,还是在起始行和停止行之间每行读取一次。我怀疑它每行读一次......并且弄清楚如何抛出额外的线条更难......但也许:
sed -i -e '/STOPSTACKOVERFLOW/r large.txt' \
-e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/d' target.txt
此版本删除了开始和结束标记。
$ cat data
sdasas
adsasdas
start
more
more
end
sdasda
sdasdad
$ cat replace
replace1
replace2
replace3
$ sed -e '/^end$/r replace' -e '/start/,/end/d' data
sdasas
adsasdas
replace1
replace2
replace3
sdasda
sdasdad
$ cat sedfile
/^end$/{
a\
start
r replace
a\
end
}
/^start$/,/^end$/d
$ sed -f sedfile data
sdasas
adsasdas
start
replace1
replace2
replace3
end
sdasda
sdasdad
$
这是比较狡猾的 - 我不会尝试在不使用脚本文件的情况下执行此操作,但如果您愿意,也可以这样做。不过,这不是一个单行。