ヒント: sortとtsortを使ってファイルを並べ換える

textutilsを知ろう

Comments

PerlやAwkを使えば、高度な並べ換えアプリケーションを記述することもできますが、つねにそうする必要もありませんし、そうした開発は、多くの場合、ひと苦労です。皆さんが必要とすることのほとんどは、sort コマンドを使っても同様に実現できますし、そのほうがずいぶん楽です。このコマンドを使えば、1個以上のファイルで行の並べ換えを行ったり、ファイルをマージしたり、そうした並べ換えが必要かどうかを調べたりすることができます。並べ換えキー (行の中の比較される部分) を指定することもできますが、指定しなくてもかまいません。指定しなければ、sort は、行全体を比較するだけのことです。

たとえば、パスワード・ファイルを並べ換えたい場合、以下のようにすればよいでしょう。(出力を直接入力ファイルに書き出すことはできません。そのようにすると、入力ファイルが壊れてしまいます。ですから、以下に示すように、まず出力を一時ファイルに書き出してから、そのファイルの名前を /etc/passwdに変更します。)

リスト1. 簡単な並べ換え
$ su -
# sort /etc/passwd > /etc/passwd-new
# mv /etc/passwd-new /etc/passwd

並べ換えの順番を逆にしたいときは、-r オプションを使います。-u オプションを使えば、まったく同じ行を表示しないようにすることもできます。

sort が非常に便利なのは、フィールド・キーを使って並べ換えを行う機能がある点です。フィールドとは、ある特定の1個の文字によって他のフィールドとの間が区切られているテキスト文字列のことです。たとえば、/etc/passwdでは、フィールドがコロン (:) によって区切られています。ですから、必要なら、/etc/passwdを ユーザーIDとか、グループID、コメント・フィールド、ホーム・カタログ、あるいはシェルによって並べ換えることができます。それには、-t オプションを使い、その後に、区切り子として使用する文字、並べ換えキーとして使用するフィールドの番号、およびキーとして使用する最後のフィールドの番号を指定します。たとえば、sort -t : -k 5,5 /etc/passwd とすると、パスワード・ファイルがコメント・フィールド (John Smithのようなユーザーの姓名が入っている部分) の順に並べ換えられます。一方、sort -t : -k 3,4 /etc/passwd とすると、同じファイルがユーザーIDとグループIDの両方を使って並べ換えられます。2番目の番号を省略すると、sort は、キーが、指定されたフィールドから始まり、行の終わりまで続くものとみなします。実際に自分でいろいろと試してみて、どんな結果になるか確かめてみてください (数字の並べ換えがうまくいかないようなときは、-g オプションを指定してください)。

なお、ホワイトスペースがデフォルトの区切り子ですので、フィールドがもともと空白文字で区切られている場合には、区切り子を省略し、-t を指定するだけでかまいません。(フィールドの番号は1から始まります。)

もっと細かい制御を行いたいときは、キーとオフセットを使います。オフセットは、-k 1.3,5.7 のように、キーをドットで区切って指定します。この例の場合、並べ換えキーが第1フィールドの3文字目から始まり、第5フィールドの7文字目で終わるという意味になります (オフセットの番号も1から始まります)。これは、どういう場合に使われるのでしょうか。私の場合、ときどきApacheのログを並べ換えるときに使用しています。キーとオフセットの表記で、日時フィールドを飛ばすことができます。

注意すべきもう一つのオプションに-b があります。これは、sort に空白文字 (スペースやタブなど) を無視させ、その行の最初の非空白文字を並べ換えキーの開始位置として処理させるというものです。このオプションを使用する場合、オフセットは、その最初の非空白文字からカウントされます (フィールド区切り子が空白文字ではなく、フィールドの文字列が空白文字で始まるものがある場合に便利です)。

並べ換えアルゴリズムは、さらに、以下のようなオプションを使って修飾することができます。-d (並べ換えキーに英字、数字、空白だけを使用する)、-f (大文字・小文字の区別をせず、小文字と大文字を同じものとして扱う)、-i (印字されないASCII文字を無視する)、-M (JAN、FEB、MARなど、3文字の月の省略名で行を並べ換える)、-n (数字、-、カンマなどの千単位の区切り記号だけを使って行の並べ換えを行う)。-b-r と同様、これらのオプションも、キー番号に含めることができます。その場合、これらのオプションは、そのキーだけに適用され、キー定義以外で使用されるときのようにコマンド全体に適用されることはありません。

キー番号の使い方として、以下の例を考えてみます。

sort -t: -k 4g,4 -k 3gr,3 /etc/passwd

これは、passwdファイルを、グループIDで並べ換え、かつグループ内をuseridで逆順に並べ換えます。

しかし、sort ができるのは、これだけではありません。使用するキーではどの行を最初にもってくるのかが決定できないような同順位状況を解決することもできます。同順位状況を解決するための条件を追加するには、もう1個-k オプションを追加し、その後に、キーを定義する際に使用したのと同じ表記方法で、フィールドと (必要に応じて) オフセットを指定します。たとえば、sort -k 3.4,4.5 -k 7.3,9.4 /etc/passwd は、3番目のフィールドの4文字目から始まり、4番目のフィールドの5文字目で終わるキーを使い、同順位状況を解決するために7番目のフィールドの3文字目と9番目のフィールドの4文字目を使って、行の並べ換えを行います。

最後に、入力ファイル、出力ファイル、一時ファイルを扱うためのオプション・グループがあります。たとえば、-c オプションは、sort -c <file という使い方をした場合、入力ファイルが並べ換え済みかどうかを調べ (他のオプションといっしょに使用できる)、並べ換え済みなら、エラーを報告します。これは、並べ換えに時間がかかりそうな大きなファイルを処理する前にチェックしておきたい場合に便利です。-c オプションといっしょに-u オプションを使用すると、入力ファイルに同じ行がダブっていないかチェックしたいという意味になります。

大きなファイルを処理するときには、一時ファイル用に、デフォルトの/tmp とは別のディレクトリーを指定するための-T オプションも重要な働きをします (一時ファイルは、sort が作業を終えると削除されます)。

sort を使って、一度に複数のファイルを処理することもできます。それには、基本的に2通りの方法があります。以下のように、最初にcat を使って複数のファイルを連結しておく方法もありますし、

cat file1 file2 file3 | sort > outfile

次のようなコマンドで実現することもできます。

sort -m file1 file2 file3 > outfile

2番目の方法の場合、条件が1つあります。入力ファイルは、sort -m に一括して渡される前に、それぞれ並べ換えられていなければならないということです。これは、不要な負担のように思えるかもしれませんが、処理速度を向上させますし、貴重なシステム資源も節約されます。-m オプションを指定し忘れないようにしてください。上のコマンドに-u オプションを指定すると、同じ内容の行を出力しないようにすることができます。

もっと難解そうな並べ換えルーチンを必要とされる方は、ファイルにトポロジカル・ソートをかけるtsort コマンドを試してみるとよいでしょう。標準の並べ換えとトポロジカルなsort の違いを、リスト2に示しておきます (happybirthday.txtは、参考文献からダウンロードできます)。

リスト2. 標準の並べ換えとトポロジカル・ソートとの違い
$ cat happybirthday.txt
Happy Birthday to You!
Happy Birthday to You!
Happy Birthday Dear Tux!
Happy Birthday to You!
$ sort happybirthday.txt
Happy Birthday Dear Tux!
Happy Birthday to You!
Happy Birthday to You!
Happy Birthday to You!
$ tsort happybirthday.txt
Dear
Happy
to
Tux!
Birthday
You!

もちろん、この例で、tsort がどんな目的で使われるのかが明瞭に示されているわけではありません。2つのコマンドの出力の違いを示すだけのものです。

tsort は、通常、観測される部分的な順序から全体の順序を予測する必要があるというような論理的な問題を解くために使用されます。たとえば (tsortのinfoページに示されている例ですが)、

tsort <<EOF a b c d e f b c d e EOF

からは、次のような結果が得られます。

a
b
c
d
e
f

質問やご意見のある方は、ぜひお聞かせください。jacek@artymiak.com までメールをいただければ幸いです。

次回は、tr を取り上げる予定です。


ダウンロード可能なリソース


関連トピック

  • リスト2の例題ファイルhappybirthday.txt はダウンロードできます。
  • これらの便利なツールの詳細については、GNUテキスト・ユーティリティー・マニュアル を参照してください。(MITには、同じ目次の展開型表示バージョン があります。MITのサイトには、さらに数多くの便利なGNUツールの素晴らしいリスト も掲載されています。)
  • Windowsユーザー向けには、これらのツールは、Cygwin パッケージとして用意されています。
  • Mac OS Xユーザーの場合、Fink を試してみるとよいでしょう。新しいなめらかなMac OS X下に豊富なUNIX環境をインストールしてくれます。
  • 何かうまくいかないことがあるという方は、GNU textutilsのFAQ (よくなされる質問)で調べてみてください。
  • 今回取り上げたツールを詳しく研究する前に、入門書的解説を読んでみたいという方は、ユーザー向けUNIXhelp から始めてみてはいかがでしょうか。
  • この分野の古典的な文献には、もちろん、O'Reilly and Associates発行のUNIX Power Tools があります (Jerry Peek、Tim O'Reilly、Mike Loukides共著、1997年刊、ISBN 1-56592-260-3)。
  • 忘れてはなりません。Jargon Fileには並べ換えについての興味深い項目が示されています。
  • このdeveloperWorks の連載でJacekが執筆した他の記事もお読みください。
  • 皆さんが今探しているLinux関係の参考文献がdeveloperWorks のLinuxゾーンで見つかるかもしれません。

コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=231475
ArticleTitle=ヒント: sortとtsortを使ってファイルを並べ換える
publish-date=03062003