![Nginx conf에서 서버 청크 및 값 추출](https://linux55.com/image/15501/Nginx%20conf%EC%97%90%EC%84%9C%20%EC%84%9C%EB%B2%84%20%EC%B2%AD%ED%81%AC%20%EB%B0%8F%20%EA%B0%92%20%EC%B6%94%EC%B6%9C.png)
AWK를 사용하여 nginx 서버 블록을 어떻게 추출할 수 있나요? 입력하다
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;
}
}
어떻게 필요한 값을 일치시키고 각 서버 블록에 대한 줄을 인쇄할 수 있나요?{}
예를 들어
Listen|root|server_name 값을 가져와야 합니다. 원하는 출력은
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
답변1
각 줄에 공백으로 구분된 여러 값이 포함될 수 있으므로 사용하기가 awk
약간 까다롭습니다 . 이는 확실히 awk에서 가능하지만 Perl과 같은 것을 사용하는 것이 더 쉽습니다.
$ perl -lne '
if(/(^| )server / || eof){
print join " ",@ll if $ll[0];
@ll=();
}
/^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2' file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
이는 -lne
"입력 파일을 한 줄씩 읽고( ), 후행 줄 바꿈을 제거하고 -n
각 호출에 줄 바꿈을 추가하고( ) 각 줄에 제공된 스크립트를 실행하는 것"을 의미합니다.print
-l
-e
암호:
if(/(^| )server / || eof){
server
: 현재 줄에 공백으로 둘러싸인 단어가 있거나 줄 시작 부분에 단어가 포함되어 있는 경우 이 섹션이 실행됩니다.print join " ",@ll if $ll[0];
: 현재 배열에 저장된 항목이 있는 경우@ll
(따라서 배열의 첫 번째 요소가 정의된 경우$ll[0]
) 공백으로 연결된 배열 내용을 인쇄합니다.@ll=();
: 다음 서버의 정보를 얻을 수 있도록 배열을 지웁니다./^(listen|root|server_name)\s+(\S[^;]+)/ && push @ll,$2'
: 이 줄이 키워드로 시작하고 하나 이상의 공백 문자가 있는 경우 공백이 아닌 첫 번째 문자와;
줄 끝까지 가능한 한 많은 비문자를 찾아 이 문자를 추가합니다(대괄호는 패턴을 캡처하므로 "this ”는 이제 인쇄용$2
배열로 전송 됩니다.@ll
awk에서 수행하는 (추악한) 방법은 다음과 같습니다.
$ awk '
(/ server\s*\{/){
if(out){
print out
}
out=""
}
($1=="listen" || $1=="root" || $1=="server_name"){
gsub(";","");
$1="";
gsub(/^ */,"");
out ? out=out" "$0 : out=$0
}
END{print out}' file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
답변2
입력 데이터에 값 쌍에 대한 레이블(또는 이름이라고도 함)이 있을 때마다 먼저 아래( )와 같은 매핑 배열을 만든 f[]
다음 어떤 조건에서든 원하는 순서로 인쇄할 수 있는 것이 가장 좋습니다. 레이블을 통해 간단히 배열 값에 액세스할 수 있습니다.
예를 들어 POSIX awk를 사용하면 다음과 같습니다.
$ cat tst.awk
(NR > 1) && ($1 == "server") { prt() }
{
tag = $1
sub(/[[:space:]]*[^[:space:]]+[[:space:]]+/,"")
sub(/;$/,"")
f[tag] = $0
}
END { prt() }
function prt() {
print f["listen"], f["server_name"], f["root"]
delete f
}
$ awk -f tst.awk file
80 domain1.com www.domain1.com html
80 domain2.com www.domain2.com /var/www/virtual/big.server.com/htdocs
문자 클래스를 지원하지 않는 POSIX가 아닌 awk를 발견하면 다음 [:space:]
으로 바꾸십시오 \t
(예: 공백 문자 뒤에 백슬래시가 오는 경우 t
).
특정 문제에 대한 출력을 얻는 더 짧은 방법이 있지만 위의 방법을 사용하면 이러한 필드와 원하는 다른 필드를 인쇄, 테스트, 재정렬, 수정하는 등의 유연성을 얻을 수 있습니다.