Pourquoi est-ce que j'obtiens cette erreur dans mon script? awk: script.awk: 19: "erreur de syntaxe

Nov 22 2020

J'ai 2 fichiers texte

1.txt

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

2.txt

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

J'essaye de générer cette 3.txtsortie:

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

et après avoir supprimé les champs en double, je devrais avoir ceci

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

En termes simples: dans deux fichiers séparés par ;(FS = ";"), si un champ $ndu fichier 1 est présent à un emplacement quelconque $mdu fichier 2, où m, n ne vaut pas 1, alors ajoutez-le $0(file2,m)à $0(file1,n). Les champs en double doivent être évités.

J'essaierai d'esquisser une solution

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

où script est le suivant:

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
}

Je dois encore marteler les doublons de nettoyage, mais probablement cela peut être fait en se divisant $0par ";"et en utilisant un tableau de comptage pour garder la trace des doublons.

Mais après avoir exécuté ce script, je renvoie des erreurs de syntaxe

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

Réponses

2 DavidC.Rankin Nov 22 2020 at 11:56

Plutôt que d'essayer des lectures séquentielles et un contrôle basé sur FNR/ NR, pourquoi ne pas utiliser getlinepour lire 2.txtet fractionner ';', puis créer la chaîne de sortie ( oci-dessous) concaténant les composants uniques de chaque ligne? Vous pouvez faire quelque chose de similaire à:

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

Exemple d'utilisation / sortie

Avec vos données d'exemple dans 1.txtet 2.txt(que vous avez à 1.txtnouveau mal nommées ), vous recevrez:

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

Ce qui ressemble à ce que vous voulez.


En tant que script prenant deux noms de fichiers comme arguments

Windows doit suivre les mêmes conventions en utilisant ARGV. Notez que vous n'incluez pas les guillemets simples autour des règles lors de l'exécution dans un awkscript, par exemple

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

( note: vous devrez changer l' /usr/bin/awkinterprète pour celui que vous avez)

L'utilisation serait, par exemple ./test.awk 1.txt 2.txt

Faites-moi savoir si cela vous a été utile.

2 glennjackman Nov 22 2020 at 13:35

L'utilisation des clés d'un tableau associatif est pratique pour gérer les éléments en double. Cela nécessite GNU awk pour le tableau multidimensionnel

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

ensuite

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

produit

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

J'aurai besoin de plus de preuves indiquant que cela "ne fonctionne pas" avec les 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;