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