Espressioni regolari dinamiche in awk
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
$ 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).