- ベストアンサー
UNIX コマンドへの引数について
- 二つのテキストファイル、file1 と file2 の内容を UNIX のコマンドで比較しようとしています。
- file1 と file2 は非常にサイズが大きく(2 - 3GB程度)、またソートされていない状態で、それぞれレコード順はバラバラです。
- comm コマンドを利用する以外の方法でより高速に実行可能な方法が有りましたら併せてご教示頂けると幸いです。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>試したところ disk に余裕が有るにもかかわらず "sort: Write error while merging" というエラーが発生し落ちてしまいました。 データが2GB以上だからですかね。例えば総計10GBのデータをソートするとしたら、/var/tmp に30-60GBくらいの容量が必要だと思いますが、大丈夫でしょうか。ワークファイルが2GBを越えないように複数ファイルに分けて作ると思います。man sortに容量の上限とか書いてないですかね。 やはり、データを分割してソートしてcommするほうが良さそうです。 awk '{a[substr($0,1,1)]++}END{for(i in a) print i,a[i]}' file1 file2 file3 | sort で、先頭文字ごとの行数が出るので、それを見て適当に分割をすればいいかと。
その他の回答 (3)
- notnot
- ベストアンサー率47% (4900/10359)
>ksh 環境で、教えて頂いた形で試してみましたが syntax error となってしまいました。 「OSやシェルによる」と書いたとおりです。SunOS + kshだと大丈夫みたいですが、OSは何でしょう? http://docs.sun.com/app/docs/doc/816-5165/ksh-1?l=ja&a=view の、Process Substitution のところ。 ファイルを分割して比較することもできますね。例えば行頭が数字だとすると、まず前半分をこのように。 cat file-a1 file-a2 file-a3 | grep '^[0-4]' | sort > file-a-0-4 cat file-b1 file-b2 file-b3 | grep '^[0-4]' | sort > file-b-0-4 comm file-a-0-4 file-b-0-4 この方が当然ソートも早いです。 named pipe を使うのは こんな感じで。 mknod /tmp/file-a p mknod /tmp/file-b p sort file-a1 file-a2 file-a3 > /tmp/file-a & sort file-b1 file-b2 file-b3 > /tmp/file-b & comm file-a file-b
補足
OS は AIX 5L ver5.1 です。 ファイル分割は、先頭がアルファベットならば grep '^[a-m]'といった感じですね。 なるほど。データの持ち方次第で使えそうです。調べてみます。 named pipe も使えそうですが、試したところ disk に余裕が有るにもかかわらず "sort: Write error while merging" というエラーが発生し落ちてしまいました。原因が分かればこちらも使えそうです。
- notnot
- ベストアンサー率47% (4900/10359)
サイズが大きいファイルをソートして比較する際に中間ファイルを作らないとするとメモリ上の処理になりますが、メモリ量は大丈夫でしょうか? OSやシェルによっては中間ファイルをメモリ上に置くことが可能です。 多くのLinuxのbashだと、 comm <(sort file1) <(sort file2) それぞれ3GBのファイルだとすると、実メモリ+スワップ領域で8GBくらいは必要でしょうね。中間ファイルを作るほうがいいと思いますよ。 ソートでなければパイプ的な処理になるので、メモリはそんなに要りませんけどソートはファイル全体の処理が終わらないと次にデータが渡らないですからね。
補足
メモリは比較的潤沢にあります。(実メモリで 12G 程度) しかし、ファイルシステム(JFS v1)の制約で、2GB 以上のファイルを作成することが出来ない為、中間ファイルを作成することが出来ません。 質問では触れていませんでしたが、file1 は最大 2GB の複数のファイルからなります。 ksh 環境で、教えて頂いた形で試してみましたが syntax error となってしまいました。
- Tacosan
- ベストアンサー率23% (3656/15482)
「UNIX のコマンド」に comm なんてあったかなぁ? さておき, シェルにも依存するような気がします. まあ最悪 mknod で named pipe を作れば何でもありだと思う.
お礼
comm を「UNIX のコマンド」と言うのは不適切なのでしょうか? すみません。。あまり詳しくないもので。 使用しているシェルは ksh です。 mknod named pipe は知りませんでした。 調べてみます。 ありがとうございます。
補足
> /var/tmp に30-60GBくらいの容量が必要だと思いますが、大丈夫でしょうか。 /var/tmp を使うと危険なので, sort -T ./ として、カレントディレクトリ(約60GBの空)を一時領域として使っていました。 おっしゃるとおり、一時ファイルが大量に最大状態で240個程出来ていました。 しかし、エラーが発生したのは、120個程度まで減少したときでした。 このとき、環境を使用していたのは、私だけでした。 これらの現象から、named pipe は挙動がつかみきれていないので、おっしゃられるように一旦、先頭文字列をみて分割したほうが良さそうですね。 本日また試してみます。