awkはストリームエディタなので、一般的な使い方は標準入力から1行ずつ(1改行ずつ)読み込んで加工をした結果を標準出力に出力していきます。
とはいえ、マッチングするテキストをメモリにため込んで、連想配列を使うことで簡単にマッチングすることができます。
このスクリプトは実際に使ったスクリプトで、データを見せることはできないのですが、雰囲気と仕組みを知ってください。
1 2 3 4 5 6 7 8 9 10 11 |
BEGIN{ FS="\t"; } FLG==1{ old[$1]=$0; next; } { if($0!=old[$1]) print; } |
このスクリプトを書くのに要した時間は5分くらいです。
old.txtとnew.txtにはタブ区切りのテキストファイルをセットしてあります。
oldの一部に不都合があって、それを修正してもらったテキストファイルがnewにセットしてあります。一部と言っても70フィールドあるなかの、どのフィールドに修正が加わったかは、現時点では不明です。
スクリプトを説明します。
BEGIN{
FS=”\t”;
}
これは常套句です。
テキストファイルのフィールド・セパレータを「タブ」に定義しています。
FLG==1{
old[$1]=$0;
next;
}
「FLG」と言う変数の値が「1」である間は、oldという連想配列にold.txtの第1フィールドを添え字にして、配列データとしては「$0」、すなわちタブ区切りのままの1レコードをセットしています。
ここで注意が必要なことは2点
「FLG==1」と、「==」にすること(代入ではなく論理演算)。
それと、「next」としないと、このスクリプトから先のスクリプトに処理がいってしまいます。
ようは、flgが「1」の間、oldと言う配列に、レコードをため込むという仕組みです。
{
if($0!=old[$1])
print;
}
肝心のマッチングは、ここで行います。
「$0」は、今読みこんだ1行のこと。
「old[$1]」は、連想配列の添え字にold.txtの最初のフィールドが使われているので、new.txtの最初のフィールドを連想配列にセットすることで、同じ値なら「$0」を呼び出すことができます。
old.txtの$0と、new.txtの$0とで値が異なれば標準出力に出力されます。
awk -f script\step1.awk FLG=1 old.txt FLG=0 new.txt>n1.txt
ここでの注意は「FLG=1」と代入することです。スクリプトでは「FLG==1」として論理演算になります。この使い分けを間違うと望んだ結果が得られませんので注意してください。
「FLG=0」としていますが「1」以外なら、値は何でも構いません。
実際にはold.txtもnew.txtも2261レコードで、スクリプトを実行した結果は635レコードでした。
70フィールドのレコード2261行をメモリに取り込んで、同じく70フィールドのレコード2261行をマッチングして635行の変更があるレコードを出力するのに要した時間は「0」秒でした。
「0」秒と言うのは正確な表現ではなく、1秒以下の計測ができないので「0」秒となっています。
つまり、スクリプトに5分、処理時間が「0」秒で目的は達成されました。
確認したいデータ件数が20万行あったとしても処理時間は1、2秒と思います。awkが32bitなので使えるメモリの領域は最大で3GigaBytesになりますが、20万行程度なら問題なく処理できます。
今度試してみますが、おそらく1千万行程度ならメモリに溜め込めると思います。処理時間含めて試したらご報告します。