msortでデータをソートする

  msort はテキストファイルをソートするためのツールである。インタフェースはコマンドラインとグラフィカルの両方があり、ファイル中の何をソートキーにし、どのようにソートするかを、いくつもの方法のなかから選択できる。

 ほとんどのLinuxシステムにインストールされているGNU sortプログラムと比べたとき、ソートキーの所在指定とソート順指定の柔軟性ではmsortが勝る。また、msortは国際化を重視していて、UTF-8を完全サポートするし、ソートキーごとに異なるロケールを用いてファイルをソートできるし、非西欧式の記数法で表された数値もサポートする。

 msortには、Gutsy(Ubuntu 7.10)、openSUSE、Fedora 7用のパッケージがあるが、本稿ではバージョン8.44を用いてソースからビルドする。msortビルドにどのような機能を取り入れたいかにより、いくつかの必須もしくは任意の依存関係がある。たとえば、非西欧式の記数法で表された数値を扱うのに、msortはUninumライブラリを使用する。もちろん、この機能が不要なら、Uninumサポートなしでmsortをコンパイルしてよい(Fedora 8といくつかのopenSUSEバージョンにはUninumパッケージがあるが、Gutsyにはない)。msortのグラフィカルインタフェースには、Tcl/Tkとiwidgetsライブラリ(Gutsy、openSUSE 10.3、Fedora 8用がある)が必要である。ソースからmsortをコンパイルするには、通常の「./configure; make; sudo make install」の手順をたどればよい。msortでUTF-8テキストを扱うには2通りのオプションがある。1つはutf8procパッケージを使うことであり、もう1つはlibicuを使うことである。msortの作者は、utf8procでなくlibicuサポートを使ってコンパイルするよう勧めている。

 ソートするデータをレコードに分割することはよく行われる。たとえば、いくつかのテキスト行をソートするとしよう。この場合、各行を1つのレコードとみなして、それぞれの一部をソートキーに指定することができる。たとえば、人名を含んでいるファイルのソートなら、ラストネームに注目して出力の順序を決める、などである。ソートキーだけではデータの完全ソートが保証されないときは、使用できる第2のソートキーを指定しておくとよいだろう。たとえば、第1のソートキーがファイル名のエクステンションなら、第2のソートキーとしてファイル名そのものを使う。こうすると、同じエクステンションを持つすべてのファイルが1つにまとまって出力され、そのファイルどうしの前後関係はファイル名によって決まることになる。

 タグ付きデータのファイルがあって、これをソートしたいとする。固定フィールド長を持たない自由形式ファイルをGNU sortで扱うことは簡単ではない。だが、次のmsort呼び出しなら、ラストネームでデータをソートできる。最初の呼び出しでは長い引数名を使用しているが、これは例をできるだけ読みやすくするためで、最後のコマンドでやっているように短い引数オプションを使っても同じソートができる。-l/--lineオプションは、各行を1つのレコードとして扱うようmsortに指示している。-t/--tagオプションは、ソートキーを探すときに正規表現を使えという指示である。

$ cat tagged-data.txt
first:Frodo last:Baggins
first:Samwise last:Gamgee
first:Meriadoc last:Brandybuck
first:Peregrin last:Took

$ msort.utf8proc --quiet --line --tag last: tagged-data.txt
first:Frodo last:Baggins
first:Meriadoc last:Brandybuck
first:Samwise last:Gamgee
first:Peregrin last:Took

$ msort.utf8proc -qlt last: tagged-data.txt

 msortは、複数行にまたがるレコードも扱える。レコードどうしの分離に特殊文字が使われているときは、--record-separatorコマンドラインオプションを指定し、msortにその文字を使わせることができる。この指定がない場合、msortは2個以上の改行文字の連続をレコード分離記号とみなす。

 以下に示すのは上と同じデータだが、レコードが複数の行にまたがっている。ここでは、--blockオプションでレコードが複数行形式になっていることをmsortに伝えたうえで、ラストネームによらず、ファーストネームでソートを実行してみよう。レコードごとにfirstタグとlastタグの順序がまちまちであることに注意してほしい。さらに、Peregrinには新しい値を追加してあるが、これは結果の並び順にまったく影響していない。

$ cat multiline-data.txt
first:Frodo
last:Baggins

last:Gamgee
first:Samwise

first:Meriadoc
last:Brandybuck

something else
first:Peregrin
last:Took

$ msort.utf8proc --quiet --block  --tag first:    multiline-data.txt
first:Frodo
last:Baggins

first:Meriadoc
last:Brandybuck

something else
first:Peregrin
last:Took

last:Gamgee
first:Samwise

 次に示すのは、ソートに複数のキーを使うことが望ましい例である。まず、第2列に基づいてソートするが、この列には100という値がいくつもある。したがって、そうしたレコードについては、つづいて第1列に基づくソートを行うと、出力が読みやすくなる。-n/--positionコマンドラインオプションは、指定のフィールドをキーとしてソートするようmsortに伝えている。フィールド間の分離にはホワイトスペースを使うのがデフォルトであり、第1列と第2列の間のスペースでデータが2つの列に正しく分割される。しかし、-d/--field-separators引数を用いて、複数のフィールド分離文字を指定することもできる。コマンドラインの中央にある-c nオプションは、指定されたキーを数値的にソートせよ、という指示である。デフォルトでは辞書的な比較が行われるため、20という値が100という値の後ろに来ることになるが、ここでは数値比較により、出力のいちばん上に置かれている。

$ cat multi-key-charnum.txt
act 100
there 100
foo 100
bar 300
urusai 300
small 20
one   20

$  msort.utf8proc --quiet --line -n 2 -c n -n 1  multi-key-charnum.txt
one   20
small 20
act 100
foo 100
there 100
bar 300
urusai 300

 -cで指定できるソート順オプションには、日付、時刻、ドメイン、電子メールアドレス、角度、ハイブリッドなど、さまざまなものがある。数値オプションにも何通りかある。ハイブリッドモードは、テキストと数値の反復パターンに基づいてフィールドを分割するというもので、システムログによくあるIPアドレスのソートに非常に便利なオプションである。次に示すのは、syslogで得たiptablesパケットレポートの部分サンプルである。これを、まずソースアドレスで、次に宛先アドレスでソートしてみよう。-t/--tagオプションでログからIPアドレスを拾い出し、-c hオプションで、どのキーについてもハイブリッド比較モードでのソートを行うよう指示する。

$ cat hybrid-ips.txt
Apr 29 20:14:58 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.3.4 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.4 DST=192.168.4.12 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth1 OUT=eth0 SRC=192.168.3.3 DST=192.168.3.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.4 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.133 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.1.33 LEN=76...

$ msort.utf8proc -ql -t SRC= -c h -t DST= -c h  hybrid-ips.txt
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.0.133 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.1.33 LEN=76...
Apr 29 20:14:58 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.2 DST=192.168.3.4 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth1 OUT=eth0 SRC=192.168.3.3 DST=192.168.3.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.4 DST=192.168.0.33 LEN=76...
Apr 29 20:15:48 fots kernel: invalides IN=eth2 OUT=eth0 SRC=192.168.3.4 DST=192.168.4.12 LEN=76...

 msortでは、ソートキーを--tag正規表現で指定できるし、そのキーの比較方法をいろいろに選択できる。このため、Perlスクリプトなどの世話にならなくても、直接、コマンドラインから多種多様なソート作業を実行できる。扱うデータの種類によっては、外国語の記数法がサポートされることも大きな利点となる。

Ben Martinは、ファイルシステムに携わって10数年。現在、PH.D.も取得し、libferris、各種ファイルシステム、検索ソリューションを中心にコンサルティング事業を展開している。

Linux.com 原文