Dynamiczne wyrażenia regularne w awk
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
AA
jest zastępowane przez d(2)
BB
jest zastępowane przez http://a.o/f/i.p?t=1
CC
jest zastępowane Link
DD
przezA_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
, BB
są 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 $0
i o oba będą traktowane jako „Dynamiczne wyrażenia regularne * w awk
mowie
Odpowiedzi
$ 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
).