使用linux bashreplace文件中两个string之间的文本

我有文件“acl.txt”

192.168.0.1 192.168.4.5 #start_exceptions 192.168.3.34 192.168.6.78 #end_exceptions 192.168.5.55 

和另一个文件“例外”

  192.168.88.88 192.168.76.6 

我需要将#start_exceptions和#end_exceptions之间的所有内容replace为exception文件的内容。 我已经尝试了这个论坛的许多解决scheme,但没有一个是可行的。

编辑

好的,如果你想保留#start和#stop,我将恢复到awk:

 awk ' BEGIN {p=1} /^#start/ {print;system("cat exceptions");p=0} /^#end/ {p=1} p' acl.txt 

感谢@fedorqui在下面的评论调整。

输出:

 192.168.0.1 192.168.4.5 #start_exceptions 192.168.88.88 192.168.76.6 #end_exceptions 192.168.5.55 

p是表示是否打印行的标志。 它从头开始为1,因此所有行都被打印,直到找到以#开始的行。 然后,我捕捉异常文件的内容并停止打印行,直到找到以#end开头的行,此时我将p标志设置回1,以便打印剩余的行。

如果你想输出到一个文件,像这样在命令的最后加上“> newfile”:

 awk ' BEGIN {p=1} /^#start/ {print;system("cat exceptions");p=0} /^#end/ {p=1} p' acl.txt > newfile 

如果您真的想要使用SED,还有其他版本

如果你确实想要用sed来做,你可以使用嵌套的地址空间,首先选择#start_exceptions和#end_exceptions之间的行,然后再选择第一行,也是除了#end_exceptions之外的行:

 sed ' /^#start/,/^#end/{ /^#start/{ n r exceptions } /^#end/!d } ' acl.txt 

输出:

 192.168.0.1 192.168.4.5 #start_exceptions 192.168.88.88 192.168.76.6 #end_exceptions 192.168.5.55 

原来的答案

我认为这将工作:

 sed -e '/^#end/r exceptions' -e '/^#start/,/^#end/d' acl.txt 

当它发现/ ^#end /它读入例外文件。 它还会删除/#start /和/#end /之间的所有内容。

为了表达技术的清晰性,我留下了略微“松散”的匹配。

您可以使用以下内容,基于将字符串替换为使用sed的文件内容 :

 $ sed $'/end/ {r exceptions\n} ; /start/,/end/ {d}' acl.txt 192.168.0.1 192.168.4.5 192.168.88.88 192.168.76.6 192.168.5.55 

说明

  • sed $'one_thing; another_thing' ac1.txt sed $'one_thing; another_thing' ac1.txt执行这两个操作。
  • /end/ {r exceptions\n}如果该行包含end ,则读取文件exceptions并将其追加。
  • /start/,/end/ {d}从包含start的行到包含end的行,删除所有行。

我在MINGW的Mark Setchell解决方案中遇到了问题。 脱字符号不是开始行。 事实上,分离器的检测是依赖于它是在行的开始? 我想出了这个awk的替代方案

 $ awk -v data="$(<exceptions)" ' BEGIN {p=1} /#start_exceptions/ {print; print data;p=0} /#end_exceptions/ {p=1} p ' acl.txt