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

时间:2014-02-19 09:39:02

标签: linux bash sed

我有文件“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之间的所有内容替换为例外文件的内容。我在这个论坛上尝试了很多解决方案,但没有一个能有效。

3 个答案:

答案 0 :(得分:14)

<强> EDITED

好的,如果您想保留#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,所以所有行都被打印,直到找到以#start开头的行。然后我捕捉异常文件的内容并停止打印行,直到找到以#end开头的行,此时我将p标志设置为1,以便打印剩余的行。

如果您想要输出到文件,请将“&gt; 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 /.

之间的所有内容

为了清楚表达这项技术,我将匹配略微“松散”。

答案 1 :(得分:3)

您可以根据Replace string with contents of a file using 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执行这两项操作。
  • /end/ {r exceptions\n}如果该行包含end,则读取文件exceptions并附加。
  • /start/,/end/ {d}从包含start的行到包含end的行,删除所有行。

答案 2 :(得分:0)

我在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