스크립트에서이 오류가 발생하는 이유는 무엇입니까? awk : script.awk : 19 :“구문 오류

Nov 22 2020

2 개의 텍스트 파일이 있습니다.

1.txt

AA;00000;
BB;11111;
GG;22222;

2.txt

KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;

3.txt출력 을 생성하려고합니다 .

AA;00000;
BB;11111;KK;WW;55555;KK;FF;ZZ;KK;RR;YY;
GG;22222;

중복 필드를 제거한 후

AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;

간단히 말해서 : ;(FS = ";") 로 구분 된 두 파일 $n에서 파일 1 의 필드 $m가 파일 2의 임의 위치 에있는 경우 m, n이 1이 아닌 경우에 추가 $0(file2,m)합니다 $0(file1,n). 중복 필드는 피해야합니다.

해결책을 스케치 해 보겠습니다.

awk -f script.awk 2.txt 1.txt

여기서 스크립트는 다음과 같습니다.

BEGIN {
    FS=";"
    OFS=";"
}

NR==FNR {
    allRecordsFile2[i++] = $0; next; } { for(r in allRecordsFile2) { split(allRecordsFile2[r],";",array) for(f in array) { for($2 through $n of file1 currently processed) { if $n == f --> $0 = $0";"allRecordsFile2[r]
             }
         }
    }

    ## cleanup duplicates

    print $0
}

나는 여전히 중복 정리를 해쳐 야하지만 아마도 이것은 중복을 추적하기 위해 계수 배열로 분할 하고 사용 $0함으로써 수행 될 수있다 ";".

하지만이 스크립트를 실행 한 후 구문 오류를 반환합니다.

C:\Program Files (x86)\GnuWin32\bin>awk -f script.awk file2.txt file1.txt

awk: script.awk:17: for($2 through $n of filei currently processed)
awk: script.awk:17: “ syntax error
awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r] awk: script.awk:19: “ syntax error awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r]
awk: script.awk:19: “ syntax error
errcount:3

답변

2 DavidC.Rankin Nov 22 2020 at 11:56

순차 읽기를 시도하고 FNR/를 기반으로 제어하는 ​​대신 각 줄에서 고유 한 구성 요소를 연결 하는 출력 문자열 ( 아래) 을 읽고 분할 한 다음 빌드하는 데 NR사용하지 않는 이유 는 무엇입니까? 다음과 유사한 작업을 수행 할 수 있습니다.getline2.txt';'o

awk '{
        printf "%s", $0 } /^BB/ { o = "" while (getline tmp < "2.txt") { n = split (tmp,arr,";") for (i=1; i<=n; i++) if(!match($0,arr[i]) && !match(o,arr[i]))
                    o=o arr[i]";"
        }
        printf "%s", o
    }
    {
        print ""
    }
' 1.txt

사용 / 출력 예시

1.txt2.txt( 1.txt다시 이름을 잘못 지정 )에 예제 데이터를 입력 하면 다음을 받게됩니다.

$ awk '{ > printf "%s", $0
>     }
>     /^BB/ {
>         o = ""
>         while (getline tmp < "2.txt") {
>             n = split (tmp,arr,";")
>             for (i=1; i<=n; i++)
>                 if(!match($0,arr[i]) && !match(o,arr[i]))
>                     o=o arr[i]";"
>         }
>         printf "%s", o
>     }
>     {
>         print ""
>     }
> ' 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;

당신이 원하는 것 같습니다.


두 개의 파일 이름을 인수로 사용하는 스크립트

Windows는 ARGV. awk스크립트 내에서 실행할 때 규칙을 작은 따옴표로 묶지 마십시오 . 예 :

#!/usr/bin/awk -f 

NR != FNR {
    exit
}
{
    printf "%s", $0
}
/^BB/ {
    o = ""
    while (getline tmp < ARGV[2]) {
        n = split (tmp,arr,";")
        for (i=1; i<=n; i++)
            if(!match($0,arr[i]) && !match(o,arr[i]))
                o=o arr[i]";"
    }
    printf "%s", o
}
{
    print ""
}

( 참고 :/usr/bin/awk 통역사를 가지고 있는 것으로 변경해야합니다 )

사용법은 다음과 같습니다. ./test.awk 1.txt 2.txt

도움이되는지 알려주세요.

2 glennjackman Nov 22 2020 at 13:35

연관 배열의 키를 사용하면 중복 항목을 처리하는 데 편리합니다. 다차원 배열을 위해 GNU awk가 필요합니다.

BEGIN { FS = OFS = ";" }
NR == FNR {
    for (i=1; i<NF-1; i++)
        f2[$(NF-1)][$i] = ++n
    next
}
FNR == 1 {
    # this joins all the 2nd-level indices
    # the order of them is undefined.
    for (x in f2) {
        s = ""
        for (y in f2[x])
            s = s y OFS
        a[x] = s
    }
}
$(NF - 1) in a { $NF = a[$(NF-1)] }
1

그때

gawk -f script.awk {2,1}.txt

생산하다

AA;00000;
BB;11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;22222;

URL에서 "작동하지 않는다"는 증거가 더 필요합니다.

$ cat 1.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;
GG;http://a.o/f/i.p?t=22222;

$ cat 2.txt KK;WW;55555;http://a.o/f/i.p?t=11111; KK;FF;ZZ;http://a.o/f/i.p?t=11111; KK;RR;YY;http://a.o/f/i.p?t=11111; $ gawk -f script.awk {2,1}.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;http://a.o/f/i.p?t=22222;