awkの動的正規表現
Nov 22 2020
私は次のようなテキストファイルを持っています
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;FF;ZZ;RR;YY
GG;22222;
この.awkスクリプトを使用します(Windowsでは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 ""
}
使用法は awk -f script.awk 1.txt 2.txt
大丈夫のようですが、この状況を考慮してください
1.txt
AA;BB;
2.txt
CC;DD;BB;AA;
今このように交換してください
AA
置き換えているd(2)
BB
に置き換えているhttp://a.o/f/i.p?t=1
CC
に置き換えられLink
DD
てA_x-y.7z
スクリプトは3.txtを生成できません
AA;BB;CC;DD;
または、置き換えられたテキストを使用すると、この3.txtテキスト出力を生成できません
d(2);http://a.o/f/i.p?t=1;Link;A_x-y.7z;
スクリプトがそのように機能するためAA
、のような重複フィールドBB
が3.txt出力から削除されていることがわかります。
私はそれが関係している疑いがある(...)
正規表現は中にグループ分けとして採用されているmatch()
最初のパラメータはREGEXあるとして渡すことで$0
、両方ともで「動的正規表現*として扱われますoをawk
話します
回答
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;
上記は、配列インデックスのハッシュルックアップでリテラル文字列を使用しているだけなので、入力にどの文字が含まれているかは関係ありません。あなたの入力はリテラル文字列として扱われたい場合は、正規表現関数や演算子を使用していない(例えばmatch()
、~
、sub()
)その上に、単に(例えば文字列関数/演算子を使用しindex()
、==
、substr()
、in
)。