Next: , Previous: , Up: Text   [Contents][Index]


33.15 テキストのソート

このセクションで説明するソート関数は、すべてバッファー内のテキストを再配置します。これはリスト要素を再配置するsort関数とは対照的です(see Rearrangement)。これらの関数がリターンする値に意味はありません。

Function: sort-subr reverse nextrecfun endrecfun &optional startkeyfun endkeyfun predicate

この関数はバッファーをレコードに細分してそれらをソートする一般的なテキストソートルーチン。このセクションのコマンドのほとんどは、この関数を使用する。

sort-subrが機能する方法を理解するためには、バッファーのアクセス可能範囲をソートレコード(sort records)と呼ばれる分離された断片に分割すると考えればよい。レコードは連続、あるいは非連続かもしれないがオーバーラップしてはならない。各ソートレコードの一部(全体かもしれない)はソートキーとして指定される。これらソートキーによるソートによりレコードは再配置される。

レコードは通常はソートキー昇順で再配置される。sort-subrの1つ目の引数reverseが非nilならレコードはソートキー降順にソートされて再配置される。

sort-subrにたいする以下の4つの引数は、ソートレコード間でポイントを移動するために呼び出される。これらはsort-subr内で頻繁に呼び出される。

  1. nextrecfunはレコード終端のポイントで呼び出される。この関数は次のレコードの先頭にポイントを移動する。sort-subrが呼び出された際には、ポイント位置が1つ目のレコードの開始とみなされる。したがってsort-subrを呼び出す前は、通常はそのバッファーの先頭にポイントを移動すること。

    この関数はバッファー終端にポイントを残すことにより、それ以上のソートレコードがないことを示すことができるできる。

  2. endrecfunはレコード内にあるポイントで呼び出される。これはレコード終端にポイントを移動する。
  3. startkeyfunはポイントをレコード先頭からソートキー先頭に移動する。この引数はオプションで、省略された場合はレコード全体がソートキーとなる。もし与えられた場合には、その関数はソートキーとして使用する非nil値、またはnil (ソートキーはそのバッファー内のポイント位置から始まることを示す)のいずれかをリターンすること。後者の場合にはソートキー終端を見るけるためにendkeyfunが呼び出される。
  4. endkeyfunはソートキー先頭からソートキー終端にポイントを移動するために呼び出される。引数はオプション。startkeyfunnilをリターンし、かつこの引数が省略(またはnil)の場合には、そのソートキーはレコード終端まで拡張される。startkeyfunが非nil値をリターンした場合にはendkeyfunは不要。

引数predicateはキーの比較に使用する関数。この関数は引数として比較する2つのキーを受け取り、1つ目のキーが2つ目のキーよりソート順で前なら非nilをリターンすること。引数のキーが正確に何であるかはstartkeyfunendkeyfunがリターンする値に依存する。predicateが省略またはnilの場合のデフォルトはキーが数値なら<、キーがコンスセル(carがキーのバッファー位置の開始でcdrが終了)ならcompare-buffer-substrings、それ以外ならstring< (キーを文字列とみなす)。

sort-subrの例として以下はsort-lines関数の完全な定義である:

;; ドキュメント文字列の冒頭2行は
;; ユーザー閲覧時には1行となることに注意
(defun sort-lines (reverse beg end)
  "リージョン内の行をアルファベット順にソート;\
 引数は降順を意味する
プログラムから呼び出す場合は、以下の3つの引数がある:
REVERSE(非nilは逆順の意)、\
およびBEGとEND(ソートするリージョン)
変数`sort-fold-case'は英字\
大文字小文字の違いが
ソート順に影響するかどうかを決定する"
  (interactive "P\nr")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (let ((inhibit-field-text-motion t))
        (sort-subr reverse 'forward-line 'end-of-line)))))

ここでforward-lineは次のレコードの先頭にポイントを移動して、end-of-lineはレコードの終端にポイントを移動する。レコード全体をソートキーとするので引数startkeyfunendkeyfunは渡していない。

sort-paragraphsはほとんど同じだが、sort-subrの呼び出しが以下のようになる:

(sort-subr reverse
           (lambda ()
             (while (and (not (eobp))
                         (looking-at paragraph-separate))
               (forward-line 1)))
           'forward-paragraph)

ソートレコード内を指す任意のマーカーは、sort-subrリターン後は無意味なマーカー位置のまま取り残される。

User Option: sort-fold-case

この変数が非nilなら、sort-subrとその他のバッファーソート関数は文字列比較時にcase(大文字小文字)の違いを無視する。

Command: sort-regexp-fields reverse record-regexp key-regexp start end

このコマンドはstartからendの間のリージョンを、record-regexpkey-regexpで指定されたようにアルファベット順にソートする。reverseが負の整数なら逆順にソートする。

アルファベット順のソートとは2つのソートキーにたいして、それぞれの1つ目の文字同士、2つ目の文字同士、...のように比較することにより、キーを比較することを意味する。文字が一致しなければ、それはソートキーが不等なことを意味する。最初の不一致箇所で文字が小さいソートキーが小さいソートキーとなる。個別の文字はEmacs文字セット内の文字コードの数値に応じて比較される。

引数record-regexpの値はバッファーをソートレコードに分割する方法を指定する。各レコードの終端で、この正規表現にたいする検索は完了して、これにマッチするテキストが次のレコードとして採用される。たとえば改行の前に少なくとも1つの文字がある行にマッチする正規表現‘^.+$’は、そのような行をソートレコードとするだろう。正規表現の構文と意味についてはRegular Expressionsを参照のこと。

引数key-regexpの値は各レコードのどの部分がソートキーかを指定する。key-regexpはレコード全体、またはその一部にマッチすることができる。後者の場合にはレコードの残りの部分はソート順に影響しないが、レコードが新たな位置に移動される際はともに移動される。

引数key-regexprecord-regexpの部分式(subexpression)、またはその正規表現自体にマッチしたテキストを参照できる。

key-regexpには以下を指定できる:

\digit

record-regexp内でdigit番目のカッコ‘\(...\)’でグループ化によりマッチしたテキストがソートキーになる。

\&

レコード全体がソートキーとなる。

正規表現

sort-regexp-fieldsは、そのレコード内で正規表現にたいするマッチを検索する。そのようなマッチがあればそれがソートキー。レコード内にkey-regexpにたいするマッチがなければそのレコードは無視されて、そのバッファー内でのレコードの位置は変更されないことを意味する(他のレコードがそのレコードを移動するかもしれない)。

たとえばリージョン内のすべての行にたいして、最初の単語が文字‘f’で始まる行をソートすることを目論むなら、record-regexpを‘^.*$’、key-regexpを‘\<f\w*\>’にセットすること。結果は以下のような式になる

(sort-regexp-fields nil "^.*$" "\\<f\\w*\\>"
                    (region-beginning)
                    (region-end))

sort-regexp-fieldsをインタラクティブに呼び出した場合にはミニバッファー内でrecord-regexpkey-regexpの入力を求める。

Command: sort-lines reverse start end

このコマンドはstartendの間のリージョン内の行をアルファベット順にソートする。reverseが非nilなら逆順にソートする。

Command: sort-paragraphs reverse start end

このコマンドはstartendの間のリージョン内のパラグラフをアルファベット順にソートする。reverseが非nilなら逆順にソートする。

Command: sort-pages reverse start end

このコマンドはstartendの間のリージョン内のページをアルファベット順にソートする。reverseが非nilなら逆順にソートする。

Command: sort-fields field start end

このコマンドはstartendの間のリージョン内の行にたいして、各行のfield番目のフィールドをアルファベット順に比較することに行をソートする。fieldは空白文字により区切られて、1から数えられる。fieldが負なら行の終端から-field番目のフィールドでソートする。このコマンドはテーブルのソートに有用。

Command: sort-numeric-fields field start end

このコマンドはstartendの間のリージョン内の行にたいして、各行のfield番目のフィールドを数値的に比較することにより行をソートする。fieldは空白文字により区切られて、1から数えられる。リージョン内の各行の指定されたフィールドは数字を含んでいなければならない。0で始まる数字は8進数、‘0x’で始まる数字は16進数として扱われる。

fieldが負なら行の終端から-field番目のフィールドでソートする。このコマンドはテーブルのソートに有用。

User Option: sort-numeric-base

この変数はsort-numeric-fieldsにたいして数字を解析するための基本基数を指定する。

Command: sort-columns reverse &optional beg end

このコマンドはbegendの間にある行にたいして特定の列範囲をアルファベット順に比較することによりソートする。begendの列位置はソートが行われる列範囲にバインドされる。

reverseが非nilなら逆順にソートする。

このコマンドが通常と異なるのは、位置begを含む行全体と位置endを含む行全体がソートされるリージョンに含まれることである。

タブは指定された列に分割される可能性があるので、sort-columnsはタブを含むテキストを受け付けないことに注意。ソート前にM-x untabifyを使用してタブをスペースに変換すること。

可能ならユーティリティプログラムsortを呼び出すことにより、このコマンドは実際に機能する。