我有以下sed命令,用start和amp;之间的文件内容替换文本块。结束标记/**#@+
和**#@-*
分别为:
sed -i -ne '/**#@+/ {p; r block.txt' -e ':a; n; /**#@-*/ {p; b}; ba}; p' -e '/**#@+/d' test.txt && sed -i -e '/**#@+/d' -e '/**#@-*/d' test.txt
(除了替换文本外,该命令还会转换行结尾。)
实际上,这会使开始和结束标记保持完整,但我也想摆脱它们。 My using the p
command means that I can't have a d
command in the same execution unit。我通过引入第二组删除这些标记的命令来解决这个问题,但如果可能的话,我想在一个单独的sed命令中使用它。
的test.txt
start of file
/**#@+
* the start marker is above
*/
this should get replaced
/**#@-*/
end marker is above
block.txt
THIS IS THE REPLACEMENT
结果
运行命令应该改变test.txt,如下所示:
start of file
THIS IS THE REPLACEMENT
end marker is above
我正在寻找sed中最短的单行解决方案。
答案 0 :(得分:1)
您的开始和结束标记包含正则表达式元字符和/
。 sed
仅按正则表达式搜索输入,您需要在/
中转义sed
和所有这些元字符。
在awk
中处理此问题要容易得多,因为awk
还允许非正则表达式纯文本搜索:
awk -v st='/**#@+' -v et='/**#@-*/' -v repl="$(<block.txt)" '
$0 == st{del=1} $0 == et{$0 = repl; del=0} !del' file
start of file
THIS IS THE REPLACEMENT
end marker is above
答案 1 :(得分:1)
虽然您说:正在寻找sed
命令,但您可能会对 Perl
perl -lae '$.==1 ? (@b="@F") : (@f="@F") && s|(^[\s+/]).*|| ||
( print /this/ ? "@b" : "@f" ) ' block file
输出
start of file
THIS IS THE REPLACEMENT
end marker is above
答案 2 :(得分:0)
这可能适合你(GNU sed):
sed '/^\/\*\*#@+/,/^\/\*\*#@-\*/cThis is the replacement' file
这会将范围之间的线条更改为所需的字符串。
要使用文件内容替换范围:
sed -e '/^\/\*\*#@+/!b;:a;N;/^\/\*\*#@-\*/M!ba;r replacementFile' -e 'd' file
在遇到范围的开始时设置一个循环来收集模式空间中的范围,然后将替换文件读入标准输出并删除模式空间的内容。