Espressioni regolari dinamiche in awk

Nov 22 2020

Ho file di testo come

1.txt

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

2.txt

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

Genero questo output 3.txt

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

con questo script .awk (lo uso in Windows con cmd)

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

L'utilizzo è awk -f script.awk 1.txt 2.txt

Sembra essere ok ma considera questa situazione

1.txt

AA;BB;

2.txt

CC;DD;BB;AA;

ora sostituisci in questo modo

AAè sostituito con d(2)
BBè sostituito con http://a.o/f/i.p?t=1
CCè sostituito con Link
DDconA_x-y.7z

lo script non può generare 3.txt

AA;BB;CC;DD;

oppure, utilizzando il testo sostituito, non è possibile generare questo output di testo 3.txt

   d(2);http://a.o/f/i.p?t=1;Link;A_x-y.7z;

Puoi vedere che i campi duplicati come AA, BBvengono rimossi dall'output 3.txt perché lo script funziona in quel modo.

Ho il sospetto che abbia a che fare con l' (...)essere preso come un raggruppamento REGEX in match()quanto il primo parametro è un REGEX e passando $0e o entrambi verranno trattati come "Espressioni regolari dinamiche * in awkparola

Risposte

1 EdMorton Nov 22 2020 at 23:36
$ cat tst.awk BEGIN { FS=OFS=";" } { key = $(NF-1) }
NR == FNR {
    for (i=1; i<(NF-1); i++) {
        if ( !seen[key,$i]++ ) { map[key] = (key in map ? map[key] OFS : "") $i
        }
    }
    next
}
{ print $0 map[key] }

$ awk -f tst.awk 2.txt 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY
GG;22222;

Quanto sopra usa solo stringhe letterali in una ricerca hash di indici di array, quindi non si preoccupa di quali caratteri hai nel tuo input. Se volete che il vostro ingresso da trattare come stringhe letterali allora non utilizzare funzioni o operatori (ad esempio, espressioni regolari match(), ~, sub()) su di esso, solo funzioni utilizzano stringhe / operatori (ad esempio index(), ==, substr(), in).