Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux sed:替换标记之间的文本块,包括标记本身_Linux_Bash_Sed - Fatal编程技术网

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

Linux sed:替换标记之间的文本块,包括标记本身,linux,bash,sed,Linux,Bash,Sed,我有以下sed命令,它们分别用开始标记和结束标记之间的文件内容替换文本块/***+和***-*: 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 (除了替换文字外,该命令还转换行尾。) 实际上,这会保留起始标记和结束标记的完整性,但我也想去掉

我有以下sed命令,它们分别用开始标记和结束标记之间的文件内容替换文本块
/***+
***-*

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
(除了替换文字外,该命令还转换行尾。)

实际上,这会保留起始标记和结束标记的完整性,但我也想去掉它们。我通过引入第二组删除这些标记的命令来解决这个问题,但是如果可能的话,我希望将所有这些都放在一个sed命令中

test.txt

start of file

/**#@+
 * the start marker is above
 */
this should get replaced
/**#@-*/
end marker is above
THIS IS THE REPLACEMENT
block.txt

start of file

/**#@+
 * the start marker is above
 */
this should get replaced
/**#@-*/
end marker is above
THIS IS THE REPLACEMENT
结果

运行该命令应更改test.txt,如下所示:

start of file

THIS IS THE REPLACEMENT
end marker is above

我正在寻找sed中最短的单行解决方案。

您的开始和结束标记包含regex元字符和
/
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
awk-vst='/***#@+'-vet='/***#@-*/'-v repl=“$”(虽然您说:正在寻找
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  
输出

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  

这可能适合您(GNU-sed):

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

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

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

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

请添加示例输入/输出,以测试您希望我们尝试什么?示例文件会很有帮助。我已从t中删除了行结束位regex&include示例输入、输出和替换文件
p
命令只打印模式空间中的内容,它们对程序流没有影响。
d
删除模式空间并结束程序流,a
d
之后的任何命令都不会执行(除非
b
t
命令指向
紧跟
d
命令的占位符)@potong感谢您的解释,很高兴了解Anks anubhava,但如上所述,我正在寻找一个只有sed的解决方案。元字符似乎对命令没有影响:我不过滤斜杠,替换效果很好。祝
sed
好运。尽管我可以但不想为这项任务升级错误的工具。顺便说一句o进一步澄清元字符您的
sed
实际上并没有搜索完整的起始标记。例如
sed-n'/***+/p'文件
也会找到一行,它只是
@+
而不是完整的
/***+
,谢谢,注意斜杠。没什么大不了的。另外,sed对我来说很好,你能提到如何用sed?app解决这个问题吗欣赏它。看看Poton的答案,你就会更好地理解为什么我要避免使用
sed
我确实在寻找sed的解决方案,但还是要感谢perl的课程!:)@foshpumpa我希望如此:)正是我想要的,非常感谢。我不能说我完全理解了,尤其是
M!ba;r
的部分,但是,嘿,它很管用