sed:替换标记之间的文本块包括标记本身

时间:2017-02-16 11:55:32

标签: linux bash sed

我有以下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中最短的单行解决方案。

3 个答案:

答案 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  

enter image description here

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed '/^\/\*\*#@+/,/^\/\*\*#@-\*/cThis is the replacement' file

这会将范围之间的线条更改为所需的字符串。

要使用文件内容替换范围:

sed -e '/^\/\*\*#@+/!b;:a;N;/^\/\*\*#@-\*/M!ba;r replacementFile' -e 'd' file

在遇到范围的开始时设置一个循环来收集模式空间中的范围,然后将替换文件读入标准输出并删除模式空间的内容。