使用linuxbash替换文件中两个字符串之间的文本



我有文件"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_exception之间的所有内容。我在这个论坛上尝试了很多解决方案,但都不起作用。

编辑

好的,如果你想保留#开始和#停止,我会恢复到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,所以所有的行都被打印出来,直到我找到一个以#start开头的行。然后,我对异常文件的内容进行cat处理,并停止打印行,直到找到以#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_exception之间的行,然后再次选择其中的第一行,以及#end_eexceptions行以外的行:

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 exceptionsn} ; /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执行这两个操作
  • /end/ {r exceptionsn}如果该行包含end,则读取文件exceptions并将其追加
  • 从包含start的行到包含end的行的/start/,/end/ {d},删除所有行

我对Mark Setchell在MINGW中的解决方案有问题。插入符号没有拾取行首。事实上,分离器的检测是否取决于它是否位于线路的起点?我想出了另一个办法。。。

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