Dynamische reguläre Ausdrücke in awk

Nov 22 2020

Ich habe Textdateien wie

1.txt

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

2.txt

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

Ich generiere diese 3.txt- Ausgabe

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

mit diesem .awk-Skript (ich benutze es in Windows mit 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 ""
}

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

Scheint in Ordnung zu sein, aber bedenken Sie diese Situation

1.txt

AA;BB;

2.txt

CC;DD;BB;AA;

jetzt auf diese Weise ersetzen

AAwird ersetzt durch d(2)
BBwird ersetzt durch http://a.o/f/i.p?t=1
CCwird ersetzt durch Link
DDdurchA_x-y.7z

Skript kann 3.txt nicht generieren

AA;BB;CC;DD;

Bei Verwendung von ersetztem Text kann diese 3.txt-Textausgabe nicht generiert werden

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

Sie können sehen, dass doppelte Felder wie AA, BBaus der 3.txt-Ausgabe entfernt werden, da das Skript auf diese Weise funktioniert.

Ich vermute , es zu tun hat mit der (...)als REGEX genommen wird Gruppierung in match()als der erste Parameter ein REGEX ist und indem $0und o beide werden als „Dynamic Reguläre Ausdrücke * in behandelt werden awksprechen

Antworten

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;

Im obigen Abschnitt werden nur Literalzeichenfolgen in einer Hash-Suche von Array-Indizes verwendet, sodass es egal ist, welche Zeichen Sie in Ihrer Eingabe haben. Wenn Sie Ihre Eingabe behandelt werden als Zeichenketten dann nicht regexp Funktionen oder Operatoren (zB match(), ~, sub()) auf ihn, nur Funktionen Verwendung Zeichenfolge / Operatoren (zB index(), ==, substr(), in).