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

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

  1. sed -n "
  2. /server\s*{/{
  3. H
  4. :loop
  5. n;H
  6. /}/{
  7. s/}//;x;H
  8. s/.*server_name\s*\([^;]*\);.*/\1/p
  9. x
  10. s/.*root\s*\([^;]*\);.*/\1/p
  11. s/.*//g;x
  12. }
  13. /{/!b loop
  14. :loop1
  15. n;H
  16. /}/!b loop1
  17. b loop
  18. }
  19. " nginx-www.centos.bz.conf

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

  1. domain="www.centos.bz"
  2. sed -i -n "
  3. /server\s*{/{
  4. H
  5. :loop
  6. n;H
  7. /}/{
  8. s/}//;x
  9. /.*server_name\s*$domain.*/d
  10. p;d
  11. }
  12. /{/!b loop
  13. :loop1
  14. n;H
  15. /}/!b loop1
  16. b loop
  17. }
  18. p
  19. " nginx-www.centos.bz.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/

标签:Nginx 发布于:2019-11-22 08:42:45