Dynamiczne wyrażenia regularne w awk

Nov 22 2020

Mam pliki tekstowe, takie jak

1. txt

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

2.txt

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

Generuję to wyjście 3.txt

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

z tym skryptem .awk (używam go w systemie Windows z 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 ""
}

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

Wydaje się być w porządku, ale rozważ taką sytuację

1. txt

AA;BB;

2.txt

CC;DD;BB;AA;

teraz wymień w ten sposób

AAjest zastępowane przez d(2)
BBjest zastępowane przez http://a.o/f/i.p?t=1
CCjest zastępowane Link
DDprzezA_x-y.7z

skrypt nie może wygenerować 3.txt

AA;BB;CC;DD;

lub używając zastąpionego tekstu, nie może wygenerować tego tekstu wyjściowego w formacie 3.txt

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

Możesz zobaczyć, że zduplikowane pola, takie jak AA, BBsą usuwane z wyjścia 3.txt, ponieważ skrypt działa w ten sposób.

Podejrzewam, że ma to związek z (...)byciem traktowanym jako grupa REGEX, match()ponieważ pierwszym parametrem jest REGEX i przez przekazanie $0i o oba będą traktowane jako „Dynamiczne wyrażenia regularne * w awkmowie

Odpowiedzi

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;

Powyższe używa po prostu ciągów literałów w wyszukiwaniu hash indeksów tablic, więc nie ma znaczenia, jakie znaki masz w danych wejściowych. Jeśli chcesz, aby wejście należy traktować jako dosłowne ciągi następnie nie używać wyrażeń regularnych funkcji lub operatorów (np match(), ~, sub()) na nim, tylko funkcje korzystają smyczkowe / operatorów (np index(), ==, substr(), in).