Dlaczego otrzymuję ten błąd w moim skrypcie? awk: script.awk: 19: „błąd składni
Mam 2 pliki tekstowe
1. txt
AA;00000;
BB;11111;
GG;22222;
2.txt
KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;
Próbuję wygenerować ten 3.txt
wynik:
AA;00000;
BB;11111;KK;WW;55555;KK;FF;ZZ;KK;RR;YY;
GG;22222;
i po usunięciu duplikatów pól powinienem to mieć
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;
W prostych słowach: w dwóch plikach, które są oddzielone ;
znakiem (FS = ";"), jeśli pole $n
z pliku 1 znajduje się w dowolnym miejscu $m
w pliku 2, gdzie m, n nie jest 1, należy dołączyć $0(file2,m)
do $0(file1,n)
. Należy unikać powielania pól.
Spróbuję naszkicować rozwiązanie
awk -f script.awk 2.txt 1.txt
gdzie skrypt jest następujący:
BEGIN {
FS=";"
OFS=";"
}
NR==FNR {
allRecordsFile2[i++] = $0; next; } { for(r in allRecordsFile2) { split(allRecordsFile2[r],";",array) for(f in array) { for($2 through $n of file1 currently processed) { if $n == f --> $0 = $0";"allRecordsFile2[r]
}
}
}
## cleanup duplicates
print $0
}
I jeszcze trzeba wypracować duplikaty czyszczenia, ale prawdopodobnie można to zrobić przez rozszczepienie $0
przez ";"
i za pomocą tablicy liczenia śledzić duplikatów.
Ale po uruchomieniu tego skryptu zwracam błędy składniowe
C:\Program Files (x86)\GnuWin32\bin>awk -f script.awk file2.txt file1.txt
awk: script.awk:17: for($2 through $n of filei currently processed)
awk: script.awk:17: “ syntax error
awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r] awk: script.awk:19: “ syntax error awk: script.awk:19: if $n == f --> $0 = $0";"allRecordsFile2[r]
awk: script.awk:19: “ syntax error
errcount:3

Odpowiedzi
Zamiast próbować odczyty sekwencyjne i sterowanie w oparciu o FNR
/ NR
, dlaczego nie użyć funkcji getline
odczytu 2.txt
i podziału, ';'
a następnie zbudowania ciągu wyjściowego ( o
poniżej), łączącego unikalne składniki z każdego wiersza? Możesz zrobić coś podobnego do:
awk '{
printf "%s", $0 } /^BB/ { o = "" while (getline tmp < "2.txt") { 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 ""
}
' 1.txt
Przykładowe użycie / wyjście
Z przykładowymi danymi w formacie 1.txt
i 2.txt
(które 1.txt
ponownie nadałeś błędnej nazwie ), otrzymasz:
$ awk '{ > printf "%s", $0
> }
> /^BB/ {
> o = ""
> while (getline tmp < "2.txt") {
> 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 ""
> }
> ' 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;
Który wygląda na to, czego chcesz.
Jako skrypt przyjmujący nazwy dwóch plików jako argumenty
Windows powinien przestrzegać tych samych konwencji, używając ARGV
. Zwróć uwagę, że nie umieszczasz pojedynczych cudzysłowów wokół reguł podczas uruchamiania w awk
skrypcie, np
#!/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 ""
}
( uwaga: będziesz musiał zmienić /usr/bin/awk
tłumacza na cokolwiek masz)
Zastosowanie byłoby np ./test.awk 1.txt 2.txt
Jeśli to pomoże, to daj mi znać.
Używanie kluczy tablicy asocjacyjnej jest przydatne do obsługi zduplikowanych elementów. Wymaga to GNU awk dla tablicy wielowymiarowej
BEGIN { FS = OFS = ";" }
NR == FNR {
for (i=1; i<NF-1; i++)
f2[$(NF-1)][$i] = ++n
next
}
FNR == 1 {
# this joins all the 2nd-level indices
# the order of them is undefined.
for (x in f2) {
s = ""
for (y in f2[x])
s = s y OFS
a[x] = s
}
}
$(NF - 1) in a { $NF = a[$(NF-1)] }
1
następnie
gawk -f script.awk {2,1}.txt
produkuje
AA;00000;
BB;11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;22222;
Potrzebuję więcej dowodów na to, że „nie działa” z adresami URL:
$ cat 1.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;
GG;http://a.o/f/i.p?t=22222;
$ cat 2.txt KK;WW;55555;http://a.o/f/i.p?t=11111; KK;FF;ZZ;http://a.o/f/i.p?t=11111; KK;RR;YY;http://a.o/f/i.p?t=11111; $ gawk -f script.awk {2,1}.txt
AA;http://a.o/f/i.p?t=00000;
BB;http://a.o/f/i.p?t=11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;http://a.o/f/i.p?t=22222;