Next: shuf invocation, Up: Operating on sorted files [Contents][Index]
sort
: テキストファイルを並べ替えるsort
は、指定されたファイルから読み込んだすべての行に対して、ソート
(sort、一定の基準に従った並べ替え)、マージ (merge、統合)、比較を行う。
ファイルが一つも指定されなかった場合や、file として ‘-’
が指定された場合は、標準入力から読み込む。デフォルトでは、sort
は結果を標準出力に書き出す。
書式:
sort [option]… [file]…
多くのオプションが、sort
が行を比較する方法に影響を及ぼす。
結果が期待と違っているときは、--debug
オプションを使って、どうしてそうなったかを調べてみていただきたい。
二つの行の比較は、次のように行われる。sort
は、対になる各フィールドを
(--key オプションを参照)、
コマンドラインで指定された順番で、そのフィールドに結びついた順序関係のオプションに従いつつ比較し、
相違が見つかるか、比較するフィールドがなくなるまでそれを続ける。
キーとなるフィールドが指定されていない場合は、デフォルトのキーである行全体が比較に使用される。
最後に、すべてのキーが同じだったときは、最後の手段として、--reverse (-r)
以外の順序関係のどんなオプションも指定されていないかのように、行全体を比較する。
--stable オプションを指定すると、この最後の手段の比較
(last-resort comparison) を行わないようになり、
その結果、すべてのキー・フィールドが等価である行は、互いに対する元の順序がそのまま維持される。
--unique (-u) オプションも、最後の手段の比較を無効にする。
別の指定がなされていないかぎり、すべての比較は、LC_COLLATE
のロケールによって指定されている文字の照合順序で行われる。2
行末の改行は、比較に当たっては、行の一部として扱われない。
入力ファイルの最後のバイトが改行でなければ、GNU の sort
は黙って改行を追加する。
GNU の sort
では (GNU のすべてのユーティリティについて規定されているとおり)、
入力行の長さに上限がない。言い換えれば、各行に含まれるバイト数に制限がない。
sort
には三つの動作モードがある。ソート (これがデフォルト)、
マージ、それに、すでにソートされているかどうかのチェックである。
動作モードの変更には、以下のオプションを使用する。
指定されたファイルがすでにソートされているかどうかをチェックする。 ファイル全体がソート済みでない場合は、診断メッセージを出し、 順番から外れている最初の箇所を示してから、ステータス 1 で終了する。 ファイルがソート済みの場合は、正常終了する。 入力ファイルは、1 個しか指定できない。
指定されたファイルがすでにソート済みだったら、正常終了する。 さもなければ、ステータス 1 で終了。入力ファイルは、1 個しか指定できない。 このオプションは -c と同様だが、診断メッセージを出さない点が異なる。
指定された複数のファイルを、一つのグループとしてソートすることで統合を行う。 各入力ファイルは、必ずそれぞれがソート済みでなければならない。 マージモードの代わりにソートモードを使えば、 そうした条件なしで、ソートとマージを行うことができる。 マージモードがあるのは、それが使える場合は、その方が高速だからである。
終了ステータス:
0: エラーが起きなかった。 1: -c や -C を付けて実行した際に、入力がソートされていなかった。 2: エラーが起きた。
環境変数 TMPDIR
が設定されていれば、sort
はその値をテンポラリ・ファイルを置くディレクトリとして /tmp の代わりに使用する。
--temporary-directory (-T) オプションは、環境変数よりさらに優先される。
以下に挙げるオプションは、出力する行の順序に影響を与える。
こうしたオプションは、グローバルなオプションとして指定することもできるし、
キーとなる特定のフィールドに対してのみ働くように指定することもできる。
キーとなるフィールドが全く指定されていない場合は、グローバルなオプションが行全体の比較に使用される。
キー・フィールドの指定がある場合は、グローバルなオプションは、
キー・フィールドのうち、それ自身のオプションが特に指定されていないフィールドに継承される。
POSIX 以前の sort
のバージョンを使用している場合、グローバルなオプションが効果を持つのは、
それより後で指定されるキー・フィールドに対してだけなので、
移植を考慮したシェルスクリプトでは、グローバル・オプションを最初に指定した方がよい。
各行中でソートに使うキーを捜すときに、文字の前にある空白を無視する。
デフォルトの空白は、スペースまたはタブだが、LC_CTYPE
のロケールによっては違うかもしれない。
なお、次のことに留意してほしい。
空白は、使用しているロケールの照合ルールによっては無視されることがあるが、
このオプションを指定しておかないと、-k オプションで指定されるキー中の文字の位置に関して、
空白が意味を持つことになる。
電話帳 (phone directory) 順にソートする。
すなわち、ソートする際にアルファベット、数字、空白以外のすべての文字を無視する。
デフォルトのアルファベットと数字は ASCII のそれであり、空白はスペースまたはタブだが、
後者は LC_CTYPE
のロケールによっては違うかもしれない。
アルファベットの小文字を、一回すべて対応する大文字に直してから、比較する。
その結果、たとえば、‘b’ と ‘B’ は等価なものとしてソートされる。
どの文字がどのタイプに属するか (訳注: たとえば、大文字か小文字か)
を決めているのは、LC_CTYPE
のロケールである。--unique
オプションと一緒に使用したとき、小文字を使っている等価な行があると、
その小文字の行は捨てられることになる。(大文字を使っている等価な行の方を捨てる方法は、
現在のところ存在しない。(--reverse オプションがあっても、
それが効果を発揮するのは、小文字の行が捨てられた後の最終結果に対してだけなのだ。))
(訳注: 実際の動作はこの説明と少し違う。最近の sort
では、
--unique と併せて使用した場合、小文字を使っている行が捨てられるのではなく、
等価な行のうち、最初に現れた行が残り、それ以外のすべてが捨てられるようである。)
各行の先頭部分を倍精度浮動小数点数 (long double-precision floating point number) に変換して、数値としてソートする。 See Floating point. オーバーフロー、アンダーフロー、変換エラーが起きても、 通知しない。行の並ぶ順番は以下のようになる。
このオプションを使うのは、他に方法がないときのみにすること。 処理速度が --numeric-sort (-n) よりずっと遅いし、 浮動小数点数に変換するとき、情報を失う恐れがある。
数値としてソートする。その際、ソートを、まず数が正か負かによって行い
(負の数、ゼロ、正の数の順)、次に SI 接尾辞 によって行い
(接尾辞なし、‘k’ や ‘K’、そして ‘MGTPEZY’ の順 see Block size)、
最後に数値によって行う。たとえば、‘1023M’ は ‘1G’ の前に来る。
SI 接尾辞として ‘M’(メガ) は ‘G’ (ギガ) の前になるからだ。
つまり、このオプションでソートする対象は、接尾辞の意味が 1000
の累乗か、1024 の累乗かを問わず、一貫したやり方で、
数値の規模にもっともふさわしい接尾辞を付けられている数値である。
従って、このオプションは、df
, du
, ls
などのコマンドに --human-readable や --si
オプションを付けて実行したときの、一回分の出力をソートするのに用いられる。
数値の書式は、--numeric-sort の場合と同じであり
(訳注: すなわち、数値の前に付けた ‘+’ 符号を理解しない)、
SI 接尾辞は、数値の後ろに直接続いていなければならない。
なお、numfmt
コマンドを使用することも考慮していただきたい。numfmt
を使用すれば、数値をソートした後で、人間に読みやすい形に整形し直すことができるので、
たいていの場合 sort
の対象に、より精密な数値を使うことが可能になるからだ。
表示できない文字を無視する。どの文字がどのタイプに属するかを決めているのは、
LC_CTYPE
のロケールである。より強力なオプションである
--dictionary-order (-d) が一緒に指定されていると、
このオプションは効果を持たない。
比較する部分の先頭が、0 個以上の空白に続いて、月名の短縮形になっているとき、
すべての文字を大文字に直して ‘JAN’ < ‘FEB’ < … < ‘DEC’
の順序で比較する。月名として無効な名前は、有効な月名より前に置かれる。
月名のつづりを決めているのは、LC_TIME
カテゴリのロケールである
(訳注: だから、英語の月名によってソートするには、ロケールを英語か
C にしておく必要がある)。デフォルトの空白は、スペースまたはタブだが、
LC_CTYPE
のロケールによっては違うかもしれない。
数値としてソートする。数値は行頭から始まり
(訳注: 比較する位置が指定されていれば、実は行頭でなくてもよい)、
任意個の空白、必要なら ‘-’ 符号、それに、0 個以上の数字から構成される。
数値は、区切り記号で 3 桁づつ区切られていてもよく、小数点記号と 0 個以上の数字が続いていてもよい。
数字がない場合は、‘0’ と見なされる。小数点記号や桁区切りの記号を規定しているのは、
LC_NUMERIC
のロケールである。デフォルトの空白は、スペースまたはタブだが、
LC_CTYPE
のロケールによっては違うかもしれない。
比較は厳密であり、丸めによるエラーはない。
このオプションは、数値に前置した ‘+’ 符号や、指数表記を理解しない。 そうした文字列を数値として比較するには、--general-numeric-sort (-g) を使用するべきである。
バージョン名とバージョン番号によってソートする。標準用法のソートと動作が似ているが、 10 進数の数字が連続する各部分をインデックス番号やバージョン番号と見なし、 (文字列としてではなく) 数値として取り扱う点が違う。 (See Details about version sort.)
比較の結果を逆順にする。その結果、出力ではより大きなキーの値を持つ行が、 後ではなく、先に表示される。
ソートを行うのに、入力中のキーをハッシュしてから、そのハッシュ値をソートするという方法を用いる。 ハッシュ関数はランダムに選択する。 その際、衝突 (collision) が絶対起きないように関数を選択するので、 値の違うキーは必ず違うハッシュ値を持つようになる。 これは、入力のランダムな並び替えに似ているが (see shuf invocation)、 同じ値を持つキーは一緒に並べるという点が、異なっている。
ランダムソートを行うフィールドが複数指定されている場合は、
ランダムに選択された一つの同じハッシュ関数が、すべてのフィールドで使用される。
フィールドごとに別のランダムなハッシュ関数を使うようにするには、
sort
を複数回呼び出せばよい。
ハッシュ関数の選択は、 --random-source オプションの影響を受ける。
その他のオプション。
テンポラリ・ファイルを prog というプログラムで圧縮する。
prog プログラムは、 引数が一つも存在しない場合に、標準入力を圧縮して標準出力に書き出し、 -d オプションの指定があれば、 標準入力を展開して標準出力に書き出すものでなければならない。
prog が 0 以外のステータスで終了した場合は、
エラーメッセージを出して、sort
の実行を中止する。
prog の指定中でホワイトスペース (訳注: 空白、タブ、改行など) やバックスラッシュ文字を使ってはならない。 そうした文字は、将来の使用のために、予約されている。
コマンドラインで名前を指定されたファイルの処理を行わない。その代わりに、
ファイル file に名前が書き込まれているファイルの処理を行う。
なお、file 中に書かれている各ファイル名は、ゼロバイト (ASCII NUL)
で終端されていなければならない。このオプションは、ファイル名のリストが長すぎて、
コマンドライン長の上限を超過してしまいそうなときに、
便利である。そうした場合、sort
を
xargs
経由で実行するのは、望ましくない。
なぜなら、xargs
はファイルのリストをいくつかの部分に分割して
sort
に渡すので、sort
はリスト全体のソートした結果ではなく、
部分リストごとのソートした結果を表示してしまうからである。
ASCII NUL で終端されたファイル名のリストを得る方法の一つは、
GNU find
に -print0 を付けて使うことである。
file に ‘-’ を指定すれば、
ASCII NUL で終端されたファイル名を標準入力から読み込むことができる。
行中の pos1 から pos2 までの部分 (両者を含む) を、ソートの対象となる場所として指定する。pos2 が省略されている場合は、 pos1 から行末までがソートの対象になる。
最も単純な形の場合、pos で指定するのは、何番目のフィールドかということである (1 から数える)。 フィールドは 1 個以上の空白文字によって区切られ、 デフォルトでは、比較するとき、そうした空白文字は各フィールドの先頭に含まれることになる。 空白文字の扱い方を調整する方法については、-b や t オプションの説明をご覧いただきたい。
より一般的に言うと、各 pos は、‘f[.c][opts]’ という形式を取る。 f は、比較に使用するフィールドは何番目かということであり、 c は、そのフィールドの始めから数えて何番目の文字かということである。 フィールドや文字の位置は、1 から数える。 なお、pos2 の文字の位置として 0 を指定すると、 そのフィールドの最後の文字を指すことになる。‘.c’ が、pos1 で省略されている場合は、デフォルトの 1 (フィールドの最初の文字) を指定したことになり、pos2 で省略されている場合は、デフォルトの 0 (フィールドの最後の文字) を指定したことになる。 opts は順序関連のオプションであり、 これを指定することで、各キーを異なったルールでソートすることが可能になる。 詳細については後述しているので、参照していただきたい。 なお、キーは複数のフィールドにまたがることができる。
たとえば、二番目のフィールドでソートするには、--key=2,2 (-k 2,2) を使用する。後述部分で、キーについてさらに説明し、 用例ももっとたくさん挙げているので、ご覧になっていただきたい。 また、--debug オプションの説明もご覧になるとよい。--debug オプションを使うと、行中のどの部分がソートに使用されているかが明らかになる。
各行のソートに使われている部分を強調表示する。 また、使用法に問題があるときは、標準エラーに警告メッセージを出す。
一度にマージする入力ファイルの数を多くても nmerge 個までとする。
nmerge 個を越える入力ファイルをマージしなければならない場合、sort
は nmerge 個のファイルからなるグループを作ってマージし、
その結果をテンポラリ・ファイルに保存する。
そして、今度はそれを入力として使用して、後に続くマージを行うのである。
nmerge の値が大きいと、実行速度が向上し、ハードディスクの一時的な使用が減るかもしれないが、 その分、メモリの使用量と I/O が増加する。 逆に、nmerge の値が小さいと、メモリに対する要求と I/O は減少するかもしれないが、 その分、ハードディスクの一時的な使用が増え、実行速度が低下することになる。
nmerge の値は、2 以上でなければならない。デフォルトの値は 16 だが、 これは実装次第なので、将来は変わるかもしれない。
nmerge の値は、オープンできるファイル・ディスクリプタの上限によって制限されているかもしれない。
‘ulimit -n’ や ‘getconf OPEN_MAX’
コマンドを使えば、使用しているシステムの上限を知ることができる。
ただし、そうした上限がさらに小さくなっていることもあり、
使用中のプログラムがすでにファイルをいくつかオープンしている場合や、
オープンできるファイルの数についてオペレーティング・システムに他の制限がある場合が、
それに当たる。nmerge がリソースの上限を越えているときは、
sort
は警告メッセージを出さずに、より小さい値を使用する。
出力を標準出力ではなく、output-file に書き出す。通常、sort
は、入力をすべて読み込んでから、output-file をオープンする。
従って、sort -o F F
や cat F | sort -o F
といったコマンドを使って、ファイルを直接書き変えるやり方でソートをすることが可能だ。
とは言え、他の用途に使用されないファイルに出力した方が、おおむね安全である。
ファイルを直接書き変えるやり方でソートしている最中に、システムがクラッシュしたり、
sort
が入出力エラーなど、深刻なエラーに遭遇したりすると、データが失われてしまいかねないからだ。
また、--merge (-m) オプションを指定した場合は、sort
は、入力をすべて読み込む前に、出力ファイルをオープンするかもしれない。
そのため、cat F | sort -m -o F - G
といったコマンドは安全ではない。
cat
が F の読み込みを済ます前に、sort
が F への書き込みを始めてしまうかもしれないからだ。
比較的新しいシステムでも、環境変数 POSIXLY_CORRECT
を設定している場合は、
たとえば ‘sort F -o F’ のように、入力ファイルの後に
-o オプションを置くことはできない。移植を考慮したスクリプトでは、
-o output-file を入力ファイルの前で指定するべきである。
file をランダムデータのソースとして使用する。そのランダムデータは、 -R オプションでどのランダムハッシュ関数を使うかを決めるのに使用される。 See Random sources.
最後の手段の比較 (last-resort comparison) を行うのを止めて、sort
を入力順尊重 (stable) にする。このオプションは、フィールド指定オプションや、
--reverse (-r) 以外のグローバルな順序関係のオプションが指定されていなければ、効果を持たない。
(訳注: いわゆる stable sort (普通、安定ソート、固定ソートと訳される) である。
たとえば、-b オプションを使って、先行する空白を無視して比較した場合に、等価となる行があったとしよう。
通常では、それでも、最後の手段の比較によって、
先行する空白の有無も考慮に入れた行全体の比較が行われ、
等価な行に順序を付けることになるが、--stable オプションが指定されていると、
それをしないので、等価な行は入力されたときの順序で出力される)。
指定された size のメインメモリをソート用のバッファとして使用する。 デフォルトでは、size は 1024 バイトを 1 単位とする数値である。‘%’ を後ろに付けると、size は、物理メモリの何パーセントの意味になる。 後置するのが ‘K’ ならば、size は 1024 倍され (デフォルトと同じ)、 ‘M’ なら 1,048,576 倍、‘G’ なら 1,073,741,824 倍される。 ‘T’, ‘P’, ‘E’, ‘Z’, ‘Y’ の後置も、同じ理屈である。 ‘b’ を後置すると、size はバイト数と見なされ、掛け算は行われない。
このオプションを指定すると、sort
は作業を始めるとき、
デフォルトよりも大きかったり、小さかったりするソート用のバッファを使用することになり、
そのために動作速度が向上することがある。
とは言え、このオプションは起動直後のバッファサイズにしか影響を持たない。
sort
が size を越える入力行に出会うと、バッファのサイズは
size 以上に拡大されるからである。
各行でソートに使うキーを探すとき、文字 separator
をフィールド・セパレータとして使用する。
デフォルトでフィールドを区分するのは、非空白文字と空白文字の間の空文字列である。
デフォルトの空白は、スペースとタブだが、LC_CTYPE
のロケールによっては、
違うかもしれない。
たとえば、入力行が ‘ foo bar’ だったとしよう。sort
はこれを
‘ foo’ と ‘ bar’ のフィールドに分割する。
フィールド・セパレータは前後どちらのフィールドにも属さないことになっている。
そこで、‘sort -t " "’ を使用した場合は、同じ入力行が、空っぽのフィールド、
‘foo’、それに ‘bar’ という 3 個のフィールドを持つことになる。
とは言え、キー・フィールドが、-k 2 のように、行末まで続く場合や、
-k 2,3 のように、範囲からなる場合は、
範囲の両端の間に存在するフィールド・セパレータは、キー・フィールド中にそのまま保持される。
ASCII NUL をフィールド・セパレータに指定するには、二文字からなる文字列 ‘\0’ を使用すればよい。‘sort -t '\0'’ のようにだ。
テンポラリファイルの置き場所にディレクトリ tempdir を使用する。
この指定は、環境変数 TMPDIR
に優先する。このオプションを二回以上指定すると、
テンポラリファイルの置き場所として、指定されたすべてのディレクトリが使用されることになる。
大規模なソートやマージを行って、I/O が足枷になる場合、このオプションを使って、
別のディスク上にあり、別のコントローラを使用している複数のディレクトリを指定すると、
実行速度が向上することがよくある。
平行して実行するソートの数を n に設定する。デフォルトでは、 n は、利用できるプロセッサーの数になっている。ただし、上限は 8 であり、これは、それ以上にしても、速度の向上が頭打ちになるからだ。 n 個のスレッドを使用すると、メモリの使用量が log n 倍になることにも注意していただきたい。 参照 nproc invocation.
通常は、等価と評価される複数の行の内、最初のもののみを出力する。 --check (-c または -C) オプションが指定されている場合は、 等価と評価される行が、2 行連続していないかをチェックする (訳注: 等価な行の連続があると、終了ステータスが 1 になる)。
また、このオプションを指定すると、デフォルトでは実行する、最後の手段の比較を行わなくなる。
コマンド sort -u
と sort | uniq
は等価である。
しかし、その等価性は、sort
に何か他のオプションが付いたときにまでは及ばない。
たとえば、sort -n -u
は、唯一性のチェックをするとき、行頭にある数字の並びの値しか調べないが、
sort -n | uniq
の方は、行全体を検査するのである。See uniq invocation.
項目の区切りに、改行 (ASCII LF) ではなく、ゼロバイトを使用する。 すなわち、入力を ASCII NUL で分離された項目として扱い、出力する各項目の末尾に ASCII NUL を付加する。このオプションは、‘perl -0’, ‘find -print0’, ‘xargs -0’ などと組み合わせて使用すると、 便利なことがある。そうしたコマンドも、わがままなファイル名を (空白などの特殊文字を含んでいる場合でも) きちんと確実に処理するために、 同様なことをしているのである。
sort
の従来の (すなわち BSD と System V の) 実装では、
いくつかのオプションの解釈が互いに異なっていた。
とりわけ、-b, -f, -n についてそうだった。
GNU の sort は、POSIX 規格の動作に従っており、
これは、たいていの場合 (常にではない!)、System V の動作と同じである。POSIX
によると、-n はもはや -b を自動的に設定しない。
そこで、動作の一貫性のために、-M も同様に変更した。
この変更によって、フィールドを指定するとき、文字の位置がどこを指すかが、
微妙なケースでは変わってくるかもしれない。
これに対する唯一の対処法は、明示的に -b オプションを指定することである。
-k によってソート・フィールドを指定するとき、 その位置指定の後ろにオプション文字 ‘MbdfghinRrV’ のうち任意のものを付けることができる。 その場合、そのフィールドは、グローバルな順序関係のオプションを一切引き継がないことになる。 -b オプションは、フィールド限定のオプションとしては、 フィールド指定の開始位置と終端位置の片方、あるいは両方に付けることができるが、 グローバル・オプションから継承した場合は、両方に付いていることになる。 入力行が、行頭やフィールド間に複数の空白を含んでいる可能性があって、 しかも -t を使っていない場合は、-k を使用するとき、-b と組み合わせるか、先行する空白を暗黙のうちに無視するオプション (すなわち ‘Mghn’) と組み合わせるのが普通だ。そうしないと、フィールドにある先行する空白の数の違いのせいで、 結果がわけのわからないものになりかねないからである。
ソートフィールド指定の開始位置が、行末より後ろや、終端側のフィールドより後ろに来てしまうと、 そのフィールドは空になる。-b オプションを指定した場合、 フィールド指定の ‘.c’ の部分は、そのフィールドの最初の非空白文字から数えることになる。
POSIX 1003.1-2001 に準拠していないシステムの sort
では、ソート・キーの指定に、‘+pos1 [-pos2]’
という 0 から数える旧来の書式が使用できる。
‘sort +a.x -b.y’ という旧来のコマンドは、
もし y が ‘0’ であるか、指定されていない場合は、
‘sort -k a+1.x+1,b’ と同じである。
それ以外の場合は、‘sort -k a+1.x+1,b+1.y’ と同じだ。
(訳注: 旧来の書式と新しい書式の違いは、フィールドやフィールド中の文字の位置を 0 から数えるか、1 から数えるかだけではない。 終端指定の位置が、旧来の書式ではキー・フィールドに含まれないのに対し (つまり、その直前までなのに対し)、新しい書式では含まれるという違いもある。 そこで、上のようになる。なお、旧来の書式であれ、新しい書式であれ、 デフォルトのフィールド・セパレータは、 「非空白文字と空白文字の間の空文字列」であることに注意していただきたい。)
この旧来の動作は、環境変数 _POSIX2_VERSION
を使えば、コントロールすることができる
(see Standards conformance)。また、POSIXLY_CORRECT
が設定されていないときに、‘-pos2’ が存在する旧来の書式を使っても、有効になる。
標準的なホストで使用することを意図したスクリプトでは、旧来の書式は使わずに、 -k の方を使用するべきである。たとえば、‘sort +2’ は使わない方がよい。 ‘sort ./+2’ と解釈されるか、‘sort -k 3’ と解釈されるか、わからないからである。 そのスクリプトが、旧来の書式にしか対応していないホストでも動作しなければならないのなら、 スクリプト中で ‘if sort -k 1 </dev/null >/dev/null 2>&1; then …’ といったテストを行って、どちらの書式を使うべきかを判断すればよい。
用例をいくつか挙げて、オプションの様々な組み合わせを説明する。
sort -n -r
sort --parallel=4 -S 10M
sort -k 3b
sort -t : -k 2,2n -k 5.3,5.4
ここで注意していただきたいが、もし -k 2,2n の代わりに -k 2n
と書いたなら、sort
は、2 番目のフィールドに始まり、行末まで続くすべての文字を、
主キー (primary key) として、それも「数値」のキーとして使用したことだろう。
sort
を実行するたいていの場合について言えることだが、
複数のフィールドにまたがるキーを数値として使用しても、期待する結果は得られないものである。
もう一つ注意していただきたい。 上の例では、‘n’ 修飾子を最初のキーのフィールド終端指定に付けている。 これは、-k 2n,2 とか -k 2n,2n とか指定しても、同じことだったろう。‘b’ を除くすべての修飾子は、 キー指定のフィールド開始側に付けるか、フィールド終端側に付けるか、 あるいは、その両方に付けるかにかかわりなく、 付けられた「キー・フィールド全体」に適用されるのである。
sort -t : -k 5b,5 -k 3,3n /etc/passwd sort -t : -n -k 5b,5 -k 3,3 /etc/passwd sort -t : -b -k 5,5 -k 3,3n /etc/passwd
この三つのコマンドは同じ働きをする。 1 番目のコマンドは、最初のキーの開始位置では先行する空白を無視し、 二番目のキーを数値としてソートするように指定している。他の二つのコマンドは、 グローバル・オプションは修飾子がないソート・キーによって継承されるという特性を利用している。 この場合、継承がうまく働くのは、-k 5b,5b と -k 5b,5 が同じことだからだ (訳注: 「-b オプションは … グローバル・オプションから継承した場合は、(開始位置と終端位置の) 両方に付いていることになる」ので、3 番目のコマンドは、-k 5b,5b と指定するのと事実上等しい)。両者が同じになるのは、‘.c’ という文字位置を欠いたフィールド終端の指定では、 先頭の空白をスキップしてもしなくても、終端位置は変わらないからである。
4.150.156.3 - - [01/Apr/2004:06:31:51 +0000] message 1 211.24.3.231 - - [24/Apr/2004:20:17:39 +0000] message 2
フィールドは、ただ 1 個の空白で区切られている。 IPv4 アドレスのソートは辞書順 (lexicographically) で行う。 たとえば、212.61.52.2 は 212.129.233.201 の前に来る。 61 は 129 よりも小さいからだ。
sort -s -t ' ' -k 4.9n -k 4.5M -k 4.2n -k 4.14,4.21 file*.log | sort -s -t '.' -k 1,1n -k 2,2n -k 3,3n -k 4,4n
この例の場合は、sort
を一回起動するだけでは、ことがすまない。
日付が空白 1 個のすぐ後に置かれているだけなのに対して、
IPv4 の構成要素は ‘.’ で区切られているからである。そこで、作業を分割し、
sort
を 2 回起動している。1 回目はタイムスタンプでソートし、
2 回目は IPv4 アドレスでソートするわけだ。タイムスタンプは、
年、月、日のフィールドの順番でソートし、最後に、時・分・秒のフィールドでソートしているが、
それは -k オプションを使って、各フィールドを分離することで実現している。
時・分・秒を除いて、各キー・フィールドの終端を指定する必要はない。
‘n’ や ‘M’ 修飾子は、フィールドの先頭にある数値や月名の短縮形に基づいてソートを行うが、
そうしたものは、フィールドの境界を越えられないからである。IPv4 アドレスのソートは、
辞書順で行っている。なお、二回目のソートで ‘-s’ を使っているのは、
主キーで一ヶ所にまとめられる行が、副キーによってソートされているようにするためである。
それに対して、一回目のソートで ‘-s’ を使っているのは、
二つのソートの組み合わせ全体を入力順尊重 (stable) にするためだ。
find src -type f -print0 | sort -z -f | xargs -0 etags --append
この例では、-print0, -z, -0 といったオプションを使っている。 そのため、空白などの特殊文字を含んでいるファイル名が、 ソート操作によって分断されることがない。
awk '{print length, $0}' /etc/passwd | sort -n | cut -f2- -d' '
一般に、あるデータが sort
コマンドでは直接ソートできないとか、
効率が悪いというとき、そうしたデータをソートするのに、この手法が役に立つ。
ls */* | sort -t / -k 1,1R -k 2,2
POSIX
以外のロケールを使用すると (たとえば、LC_ALL
を ‘en_US’
に設定すると)、sort
の出力が、見慣れない順序でソートされたものになるかもしれない。
その場合は、環境変数 LC_ALL
を ‘C’ にすればよい。
注意すべきは、LC_COLLATE
だけを設定したのでは、二つの問題が生じてしまうということだ。
一つは、LC_ALL
も設定されている場合、LC_COLLATE
は無効だということ。二つ目は、LC_CTYPE
が
(LC_CTYPE
が設定されていないときは、LANG
が)
LC_COLLATE
と矛盾する値に設定されている場合、動作が未定義だということである。
たとえば、LC_CTYPE
が ja_JP.PCK
であるのに、
LC_COLLATE
が en_US.UTF-8
の場合、sort
の動作は未定義なのである。
Next: shuf invocation, Up: Operating on sorted files [Contents][Index]