Warum erhalte ich diesen Fehler in meinem Skript? awk: script.awk: 19: “Syntaxfehler

Nov 22 2020

Ich habe 2 Textdateien

1.txt

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

2.txt

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

Ich versuche diese 3.txtAusgabe zu generieren :

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

und nachdem ich doppelte Felder entfernt habe, sollte ich dies haben

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

In einfach Worten: in zwei Dateien , die getrennt sind durch ;(FS = „;“), wenn ein Feld $nvon Datei 1 , die in einem beliebigen Ort $min der Datei 2, wobei m, n nicht 1 ist , dann append $0(file2,m)zu $0(file1,n). Doppelte Felder müssen vermieden werden.

Ich werde versuchen, eine Lösung zu skizzieren

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

Dabei ist das Skript wie folgt:

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
}

Ich brauche immer noch die Bereinigung um Duplikate zu hämmern, aber wahrscheinlich kann dies durch Spaltung erfolgen $0durch ";"und eine Zählung Array Spur von Duplikaten zu halten.

Aber nachdem ich dieses Skript ausgeführt habe, gebe ich Syntaxfehler zurück

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

Antworten

2 DavidC.Rankin Nov 22 2020 at 11:56

Anstatt sequenziell versuchen liest und Steuern basierend auf FNR/ NR, warum nicht verwenden , getlineliest aus 2.txtund Split auf ';'und dann die Ausgabezeichenfolge bauen ( ounten) aus jeder Zeile einzigartige Komponenten verketten? Sie könnten etwas Ähnliches tun wie:

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

Beispiel Verwendung / Ausgabe

Mit Ihren Beispieldaten in 1.txtund 2.txt(die Sie 1.txterneut falsch benannt haben ) erhalten Sie:

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

Welches sieht aus wie was Sie wollen.


Als Skript, das zwei Dateinamen als Argumente verwendet

Windows sollte die gleichen Konventionen wie verwenden ARGV. Beachten Sie, dass Sie die einfachen Anführungszeichen nicht in die Regeln aufnehmen, wenn Sie in einem awkSkript ausgeführt werden, z

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

( Hinweis: Sie müssen den /usr/bin/awkInterpreter auf das ändern , was Sie haben.)

Verwendung wäre zB ./test.awk 1.txt 2.txt

Lassen Sie mich wissen, ob das hilft.

2 glennjackman Nov 22 2020 at 13:35

Die Verwendung der Schlüssel eines assoziativen Arrays ist praktisch, um doppelte Elemente zu verarbeiten. Dies erfordert GNU awk für das mehrdimensionale Array

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

dann

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

produziert

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

Ich brauche mehr Beweise dafür, dass es mit URLs "nicht funktioniert":

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