Text-Processing

從 Nginx conf 中提取伺服器的塊

  • June 16, 2021

我有以下用於 nginx 的 conf 文件:

user       www www;  ## Default: nobody
...

events {
 worker_connections  4096;  ## Default: 1024
}

http {
 include    conf/mime.types;
 ...

 server { # php/fastcgi
   listen       80;
   server_name  domain1.com www.domain1.com;
   access_log   logs/domain1.access.log  main;
   root         html;

   location ~ \.php$ {
     fastcgi_pass   127.0.0.1:1025;
   }
 }

 server { # simple reverse-proxy
   listen       80;
   server_name  domain2.com www.domain2.com;
   access_log   logs/domain2.access.log  main;

   # serve static files
   location ~ ^/(images|javascript|js|css|flash|media|static)/  {
     root    /var/www/virtual/big.server.com/htdocs;
     expires 30d;
   }

   # pass requests for dynamic content to rails/turbogears/zope, et al
   location / {
     proxy_pass      http://127.0.0.1:8080;
   }
 }
}

這是foo我在 www.nginx.com 上找到的一個範例。

目標是提取所有伺服器的塊以進行各種處理。在這種特殊情況下,我感興趣的是兩個伺服器塊。

因為我在非常有限的環境中工作,所以我只能使用 sed/grep/awk/unix 系統命令。沒有蟒蛇,沒有珍珠,…

這種配置文件的問題在於,塊本身可能server包含一些子塊(即server { ... directive { ... }})。考慮到這一點,不可能簡單地使用grep -oP "server {.*?}".

grep勝任嗎?我嘗試了許多不同的正則表達式,但沒有找到好的。現在,我使用沒有反斜杠的上述文件(即cat $FILE | tr -d "\n")。我已經嘗試過類似的東西,grep -oP "server\s{1,}{.*?({.*?}){0,}}"但它不符合我的需求……

我想使用的原因grep是我認為這awk不是很可讀,並且維護程式碼應該更容易grep- 但如果使用awk!

謝謝 :)

編輯:

輸出應如下所示:

"server { # php/fastcgi
 listen       80;
 server_name  domain1.com www.domain1.com;
 access_log   logs/domain1.access.log  main;
 root         html;

 location ~ \.php$ {
   fastcgi_pass   127.0.0.1:1025;
 }
}",
"server { # simple reverse-proxy
 listen       80;
 server_name  domain2.com www.domain2.com;
 access_log   logs/domain2.access.log  main;

 # serve static files
 location ~ ^/(images|javascript|js|css|flash|media|static)/  {
   root    /var/www/virtual/big.server.com/htdocs;
   expires 30d;
 }

 # pass requests for dynamic content to rails/turbogears/zope, et al
 location / {
   proxy_pass      http://127.0.0.1:8080;
 }
}"

我可以使用諸如echo $OUTPUT | tr -d ... | grep -v .... 如果可能的話,我希望在一行中提取每個伺服器塊以循環結果!

如果我理解正確,您正在尋找類似的東西:

$ awk '/server *{/{c=1; print;next} c&&/{/{c++} c&&/}/{c--} c' file
 server { # php/fastcgi
   listen       80;
   server_name  domain1.com www.domain1.com;
   access_log   logs/domain1.access.log  main;
   root         html;

   location ~ \.php$ {
     fastcgi_pass   127.0.0.1:1025;
   }
 }

 server { # simple reverse-proxy
   listen       80;
   server_name  domain2.com www.domain2.com;
   access_log   logs/domain2.access.log  main;

   # serve static files
   location ~ ^/(images|javascript|js|css|flash|media|static)/  {
     root    /var/www/virtual/big.server.com/htdocs;
     expires 30d;
   }

   # pass requests for dynamic content to rails/turbogears/zope, et al
   location / {
     proxy_pass      http://127.0.0.1:8080;
   }
 }

解釋

  • /server *{/{c=1; print; next;}: 如果這一行匹配server, 0 個或多個空格,然後是 a {,則將變數設置c為 1。因此,c每次我們找到一個新server{塊時,都會為 1。然後print該行並跳到該行next
  • c&&/{/{c++}: 如果c定義了而不是 0,並且此行匹配 a {,則遞增c1 ( c++)。這可以寫成if(c && /{/){ c=c+1}. 因此,每個找到的嵌套塊的值c都會增加。{
  • c&&/}/{c--}: ifc被定義而不是 0,並且這一行匹配}, 減c1。這可以寫成if(c && /}/){c=c-1}。這確保了隨著每個嵌套塊的關閉, 的值c會下降。{}
  • c: 這是一個awk技巧。當某事計算為真時的預設操作awk是列印目前行。在這裡,它將列印是否c已定義而不是 0(真)。由於上面的命令c根據我們是否在一個server塊中而增加和減少,這將導致只列印你所追求的行。

引用自:https://unix.stackexchange.com/questions/293316