Text-Processing
從 Nginx conf 中提取伺服器的塊
我有以下用於 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。然後next
。c&&/{/{c++}
: 如果c
定義了而不是 0,並且此行匹配 a{
,則遞增c
1 (c++
)。這可以寫成if(c && /{/){ c=c+1}
. 因此,每個找到的嵌套塊的值c
都會增加。{
c&&/}/{c--}
: ifc
被定義而不是 0,並且這一行匹配}
, 減c
1。這可以寫成if(c && /}/){c=c-1}
。這確保了隨著每個嵌套塊的關閉, 的值c
會下降。{}
c
: 這是一個awk
技巧。當某事計算為真時的預設操作awk
是列印目前行。在這裡,它將列印是否c
已定義而不是 0(真)。由於上面的命令c
根據我們是否在一個server
塊中而增加和減少,這將導致只列印你所追求的行。