Dlaczego otrzymuję ten błąd w moim skrypcie? awk: script.awk: 19: „błąd składni

Nov 22 2020

Mam 2 pliki tekstowe

1. txt

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

2.txt

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

Próbuję wygenerować ten 3.txtwynik:

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

i po usunięciu duplikatów pól powinienem to mieć

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

W prostych słowach: w dwóch plikach, które są oddzielone ;znakiem (FS = ";"), jeśli pole $nz pliku 1 znajduje się w dowolnym miejscu $mw pliku 2, gdzie m, n nie jest 1, należy dołączyć $0(file2,m)do $0(file1,n). Należy unikać powielania pól.

Spróbuję naszkicować rozwiązanie

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

gdzie skrypt jest następujący:

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
}

I jeszcze trzeba wypracować duplikaty czyszczenia, ale prawdopodobnie można to zrobić przez rozszczepienie $0przez ";"i za pomocą tablicy liczenia śledzić duplikatów.

Ale po uruchomieniu tego skryptu zwracam błędy składniowe

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

Odpowiedzi

2 DavidC.Rankin Nov 22 2020 at 11:56

Zamiast próbować odczyty sekwencyjne i sterowanie w oparciu o FNR/ NR, dlaczego nie użyć funkcji getlineodczytu 2.txti podziału, ';'a następnie zbudowania ciągu wyjściowego ( oponiżej), łączącego unikalne składniki z każdego wiersza? Możesz zrobić coś podobnego do:

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

Przykładowe użycie / wyjście

Z przykładowymi danymi w formacie 1.txti 2.txt(które 1.txtponownie nadałeś błędnej nazwie ), otrzymasz:

$ 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;

Który wygląda na to, czego chcesz.


Jako skrypt przyjmujący nazwy dwóch plików jako argumenty

Windows powinien przestrzegać tych samych konwencji, używając ARGV. Zwróć uwagę, że nie umieszczasz pojedynczych cudzysłowów wokół reguł podczas uruchamiania w awkskrypcie, np

#!/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 ""
}

( uwaga: będziesz musiał zmienić /usr/bin/awktłumacza na cokolwiek masz)

Zastosowanie byłoby np ./test.awk 1.txt 2.txt

Jeśli to pomoże, to daj mi znać.

2 glennjackman Nov 22 2020 at 13:35

Używanie kluczy tablicy asocjacyjnej jest przydatne do obsługi zduplikowanych elementów. Wymaga to GNU awk dla tablicy wielowymiarowej

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

następnie

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

produkuje

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

Potrzebuję więcej dowodów na to, że „nie działa” z adresami 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;