スクリプトでこのエラーが発生するのはなぜですか?awk:script.awk:19:「構文エラー
私は2つのテキストファイルを持っています
1.txt
AA;00000;
BB;11111;
GG;22222;
2.txt
KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;
私はこの3.txt
出力を生成しようとします:
AA;00000;
BB;11111;KK;WW;55555;KK;FF;ZZ;KK;RR;YY;
GG;22222;
重複するフィールドを削除した後、これが必要です
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY;
GG;22222;
簡単に言うと、;
(FS = ";")で区切られた2つのファイルで$n
、ファイル1のフィールド$m
がファイル2の任意の場所に存在し、m、nが1でない場合は、に追加$0(file2,m)
し$0(file1,n)
ます。重複するフィールドは避ける必要があります。
解決策をスケッチしてみます
awk -f script.awk 2.txt 1.txt
スクリプトは次のとおりです。
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
}
私はまだクリーンアップの重複を打ち出す必要がありますが、おそらくこれは、重複を追跡するためにカウント配列で分割$0
し";"
て使用することで実行できます。
しかし、このスクリプトを実行した後、構文エラーが返されます
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

回答
順次読み取りを試みてFNR
/NR
に基づいて制御するのではなく、を使用getline
して読み取り2.txt
と分割を';'
行い、o
各行の一意のコンポーネントを連結する出力文字列(以下)を作成してみませんか?次のようなことができます。
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
使用例/出力
1.txt
および2.txt
(1.txt
再度名前を間違えた)のサンプルデータを使用すると、次のようになります。
$ 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;
それはあなたが望むもののように見えます。
2つのファイル名を引数として取るスクリプトとして
Windowsは、を使用して同じ規則に従う必要がありますARGV
。awk
スクリプト内で実行する場合は、ルールを一重引用符で囲まないように注意してください。
#!/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 ""
}
(注:/usr/bin/awk
インタプリタをお持ちのものに変更する必要があります)
使用法は、例えば ./test.awk 1.txt 2.txt
それが役立つかどうか教えてください。
連想配列のキーを使用すると、重複するアイテムを処理するのに便利です。これには、多次元配列用のGNUawkが必要です
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
その後
gawk -f script.awk {2,1}.txt
を生成します
AA;00000;
BB;11111;55555;WW;KK;RR;YY;FF;ZZ;
GG;22222;
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;