mysql 开源 apache HTML5 程序员 Firefox nginx shell 微软 linux Python Android google java linux命令 php Ubuntu Windows centos wordpress

使用sed对nginx配置文件进行删除和列出虚拟主机操作

带着需要使用sed来对Nginx配置文件进行操作的强烈需求,于是开始了学习sed的高级应用。虽然之前也一直在用sed,但也只是接触到了s替换命令,其它高级的命令没用到,所以没有动力去学。一直觉得要学到点东西,前提是你现在有一问题,需要用到这个技术来解决,而且有强烈的渴望要把这个问题解决,这时候你学习这项技术会事半功倍。否则学习起来会非常的枯燥无味,效率低,甚至会放弃。下面是我最近学sed得出的成果,备忘一下,以防失忆。

一、列出所有虚拟的server_name和对应的root

sed -n "
/server\s*{/{
H
:loop
n;H
/}/{
s/}//;x;H
s/.*server_name\s*\([^;]*\);.*/\1/p
x
s/.*root\s*\([^;]*\);.*/\1/p
s/.*//g;x
}
/{/!b loop
:loop1
n;H
/}/!b loop1
b loop
}
}
" nginx-www.linuxde.net.conf

二、删除指定server_name的虚拟主机

domain="www.linuxde.net"
sed -i -n "
/server\s*{/{
H
:loop
n;H
/}/{
s/}//;x
/.*server_name\s*$domain.*/d
p;d
}
/{/!b loop
:loop1
n;H
/}/!b loop1
b loop
}
p
" nginx-www.linuxde.net.conf

代码有点多,就不具体分析了,具体说下如何找出server {} 代码块。

代码分析:

1、首先先关闭自动打印功能,即-n选项,因为下面会用到n命令,会自动打印,所以添加-n之后,使用n命令就不会自动打印了,需要打印时,使用p命令。

2、匹配 server {,如果匹配到,则把pattern space的内容添加到hold space,然后进入loop循环,执行n命令(n命令不必进入新的循环读取下一步到pattern space),再用H附加到hold space

3、判断是否找到代码块结束符},如果找到,进入server {}代码块处理阶段,处理完之后,进入下一个循环,继续找出下一个server{}。

4、如果找不到,再判断是否找到{,如果没有找到,进入loop循环

5、如果找到了{,表示存在if {},或者location {},则必要找到两个}才算是完整的server代码块。此时进入loop1循环,n命令读取下一行,附加到hold space。

6、再判断是否找到},如果没有找到,继续loop1循环,如果找到了,还需要一个},所以跳到loop循环。

7、如此循环下来,直接找到完整的server代码块。

关键的几点提示:

1、n命令是直接清空pattern space,并读取下一行到pattern space,而不需要进入新的循环。在这里的作用是,因为要把pattern space的内容附加到hold space,所以每读取一行,必需先清空pattern space,然后再附加到hold space,这样hold space才不会出现重复内容。要达到清空pattern space,读取下一行,进入下一循环可以做到,但进入下一循环后,必需重新匹配server {,而下一行肯定无法匹配,所以就达不到累积的效果。

2、hold space在这里很重要,它的内容来自pattern space对其进行附加操作。累积到完整的server代码块时,再与pattern space进行交换,交换之前必需把pattern space清空,这样交换后,hold space才能为空,为累积出下一个server代码块做准备。

最后还是建议使用sed的debug工具sedsed查看pattern space和hold space的变化。http://aurelio.net/projects/sedsed/

延伸阅读

评论