awk 명령을 awk 스크립트로 변환(다중 F)

awk 명령을 awk 스크립트로 변환(다중 F)

작업 명령이 있습니다

awk  -F '[)#/(:]' 'BEGIN  { fw="";dev=""} {if ($0~/sh failover/) fw=$1 ; if (($0~/This host/)||($0~/Other host/)) dev=$2; if ($0~/\)\:/) {print $2,$1,fw, dev} }' OFS="|" test_data

이것을 스크립트로 만들고 싶습니다. 이 일을 할 때 ...

#!/bin/sh
awk '
BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} 
{
    if ($0~/sh failover/) fw=$1 ; 
    if (($0~/This host/)||($0~/Other host/)) dev=$2; 
    if ($0~/\)\:/) {
        print $2,$1,fw, dev
        } 
}' test_data 

...F='[)#/(:]' 오류가 발생합니다.

[...srv01]$ ./test
./test: line 3: syntax error near unexpected token `)'
./test: line 3: `BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} '
[...srv01]$ 

큰따옴표로 변경하면 큰따옴표 사이의 모든 내용이 구분 기호로 표시되므로 대신 )#/(: 을 찾습니다.)또는#또는/또는(또는:

test_data의 파일 내용입니다.

[...srv01]$ cat test_data
JoeASA# sh failover | i \)\:|host
        This host: Primary - Active
                  admin Interface management (313.13.0.13): Normal (Monitored)
                  DMZ-FW Interface Inside (310.13.19.7): Normal (Not-Monitored)
                  DMZ-FW Interface Outside-Zone2 (912.168.119.7): Normal (Not-Monitored)
                  ENET Interface OUTSIDE(912.168.191.7): Normal (Not-Monitored)
                  ENET Interface dmarc (912.168.192.7): Normal (Not-Monitored)
                  GW Interface Extranet (912.168.23.27): Normal (Not-Monitored)
                  GW Interface Outside-Zone (912.168.123.27): Normal (Not-Monitored)
                  GW Interface management (331.1.1.47): Normal (Not-Monitored)
        Other host: Secondary - Standby Ready
                  admin Interface management (313.13.0.12): Normal (Monitored)
                  DMZ-FW Interface Inside (310.13.19.6): Normal (Not-Monitored)
                  DMZ-FW Interface Outside-Zone2 (912.168.119.6): Normal (Not-Monitored)
                  ENET Interface OUTSIDE(912.168.191.6): Normal (Not-Monitored)
                  ENET Interface dmarc (912.168.192.6): Normal (Not-Monitored)
                  GW Interface Extranet (912.168.23.26): Normal (Not-Monitored)
                  GW Interface Outside-Zone (912.168.123.26): Normal (Not-Monitored)
                  GW Interface management (331.1.1.46): Normal (Not-Monitored)          
SIMPLEASA1/sec/act#  sh failover | i \)\:|host
        This host: Secondary - Active
                  Interface Edge (912.168.22.17): Normal (Monitored)
                  Interface Inside (310.13.19.17): Normal (Monitored)
                  Interface EXT (912.168.50.17): Normal (Monitored)
                  Interface WIFI (912.168.11.17): Normal (Monitored)
        Other host: Primary - Standby Ready
                  Interface Edge (912.168.22.16): Normal (Monitored)
                  Interface Inside (310.13.19.16): Normal (Monitored)
                  Interface EXT (912.168.50.16): Normal (Monitored)
                  Interface WIFI (912.168.11.16): Normal (Monitored)                      
[..srv01]$ 

답변1

쉘에서 작은따옴표로 묶인 문자열로 awk에 스크립트를 전달하고 있지만 작은따옴표가 있는 것 같습니다.~에대본도 마찬가지다. 실제로는 인용된 문자열을 끝냅니다.

awk 'BEGIN  {F='[)#/(:]'; FS = "\n"; RS = ""; OFS = "|";fw="";dev=""} 
                ^^^^^^^ not quoted

쉘은 따옴표 없이 하나를 보고 )구문 오류가 발생합니다. 어쨌든 awk 스크립트에서 작은따옴표를 사용하고 싶지 않으면 구문 오류가 발생합니다.갑자기. 따라서 다른 할당과 마찬가지로 큰따옴표를 사용하면 셸에서 작은따옴표에 잘 맞고 실제로 awk 코드에서 작동합니다.

awk 'BEGIN { foo="bar"; ...}'

그런 다음 awk의 옵션은 대신 -F변수인 필드 구분 기호를 설정한다는 점에 유의하십시오 . 따라서 당신은 을 갖고 싶어 하고 아마도 기본 레코드 구분 기호를 변경하고 싶지 않을 것입니다 . 적어도 위 줄에서는 변경하지 않았습니다.FSFBEGIN { FS="[)#/(:]"; ...RS


/usr/bin/awk또는 awk 스크립트를 쉘 스크립트에 넣는 대신 쉘을 건너뛰고 awk를 스크립트에 대한 인터프리터로 직접 만들 수 있습니다(awk가 거기에 있다고 가정 ).

#!/usr/bin/awk -f
BEGIN { FS="[)#/(:]"; OFS="|"; fw=""; dev=""} 
{
    if ( $0 ~ /sh failover/ ) fw=$1 ; 
    if (($0 ~ /This host/) || ($0 ~ /Other host/)) dev=$2; 
    if ( $0 ~ /\)\:/ ) {
        print $2, $1, fw, dev
    } 
}

호출되고 ./script.awk실행 가능한 경우 로 실행할 수 있습니다 ./script.awk filename. 즉, 파일을 사용하여 스크립트에 대한 인수로 처리할 수 있습니다.

관련 정보