« 2013年8月 | トップページ | 2013年10月 »

2013年9月

2013年9月30日 (月)

[vim]行をソート(sort)する

[vim]行をソート(sort)する

Time-stamp: "Sat Dec 29 15:53:47 JST 2012"

住所録を氏名の五十音順にソートしたい。コマンドラインツールにsortコマ ンドがある。windows7にもsortコマンドがある。これを使えば出来そうであ る。

データは csv(comma separated value)で作っている。第一フィールドが氏 名の読み仮名(カタカナ)、第二フィールドが漢字氏名、第三フィールドが住 所、…のようにしている。第一フィールドでソートしたい。

ところでソートコマンドは、テキストファイルの一行ごとの先頭(第一番目) の文字に対して、その文字に付けられた背番号(文字コード)により並べ換え る。次に各行の第一番目の文字の順番を崩さないように(第一番目に同じ文 字がある行のグループ内で)第二番目の文字の背番号順に並べ換える。この 作業を行の末尾の文字まで繰り返す。行頭から何文字目かまでが一致する行 のグループで各行の文字数が大小マチマチだったら短かい行ほど先に順番が 確定する。

もし、氏名の読み仮名が第一フィールドにない場合はawkスクリプトなどに よるフィルタ処理で、フィールドを入れ替える処理が必要になる。氏名の読 み仮名を第一フィールドにしておけばsortコマンドだけで氏名の読み仮名を 五十音順にソートできる。

本当は第一フィールドの氏名の読み仮名だけに限定してソートすべきだが、 そうすると却って面倒になる。読み仮名氏名、漢字氏名、住所をひっくるめ た一行全体を対象にしてソートする。もし読み仮名氏名に同姓同名があった なら漢字氏名以降にソートが及ぶ(ソートコマンドは行の先頭から末尾まで が対象になる。読み仮名氏名だけでソートを止めるのは難しい)。個人の住 所録であれば同姓同名が何人もいることは考えられない。仕上げを目視でや れば問題ない。

vimならexコマンドにより「:[range]!sort」とすれば、その部分をvimの編 集画面に表示したままで処理が実行できる。windows7のsortコマンドに渡さ れて処理することになるけれど、windows7のコマンドプロンプトは表示され ない。vimの編集画面が表示されたままで該当部分がソートされた結果に入 れ替わる。[range]は開始行と終了行の行番号をカンマで区切ったものなど で指定する。

処理する範囲を行番号で指定する。ファイル全体にsortコマンドを実行する と住所データでない部分までがソートされてしまう。一つの住所録に家族何 人分も入れ込むときは家族一人一人の部分毎にソートできる。外部コマンド のsortを使う方法は「:help :!」で読めるヘルプ参照。

windows7のsortコマンドは、引き数として指定したファイルの全部の行を対 象にしてソートを実行する。住所録ファイルには、csv形式の住所データに 加えて誰のデータであるとかファイルの更新時刻やメモ書きなども書き込ま れている。普通にwindows7のコマンドプロンプトからsortコマンドを実行す るとcsv形式のデータ部分だけでなくメモ書きなどのコメントを含めてソー トされる。コメントが何行にも渡る文章であったならそれらの行順が変更さ れてズタズタになる。そのときは住所データ部分だけを範囲指定してソート する。

vimは、外部コマンドの作用範囲を開始行番号と終了行番号で指定できる。 住所データでない部分にはソートが及ばないようにできる。そのようなこと を知らない今迄はcsv形式のデータ部分だけを一時(中間)ファイルに書き出 す。そしてその中間ファイルに対してwindowsのコマンドプロンプトから ソートコマンドを実行する。その結果(別ファイル)で元ファイルの該当部分 を置き換えるという面倒なことをしていた。出来ることは出来るけれど煩雑 なために、どうしても必要な場合しかソートする気にならない。データが 20~30個程度ならエディタ画面を見ながら行を入れ替える。50~60個にもな ると、もてあます。そういうときにvimのソートは便利である。

windows7のコマンドプロンプトで中間ファイルをsort作業する間はテキスト エディタから離れた別作業(下請け仕事、内職)になってしまう。ソートコマ ンドで処理した結果で元ファイルの相当部分を置き換えるのはエディタ画面 上での作業になる。vimなら画面上の指定範囲内だけのソートができる。外 部コマンドのsortによる並べ替えが、エディタの編集画面を表示したままで コマンドプロンプトの画面に切り替わることもなく裏面の隠れたところで密 かに行われる。ソートコマンドを実行したら編集画面にすぐ結果となって現 われる。エディタの編集マクロを使った感じだろう。

試しに約5000行のテキストファイルをvimに表示させた状態で「:%!sort」を 実行してみる。画面が真っ白になり何も表示されない。実際は空行が表示さ れていたのだが、最初はそのことに気が付かなかった。ファイルが空なら vimは第一行に続く画面の空きスペースにチルダ文字を表示するはずであ る。ひょっとしてvimがフリーズしたのかとメニューバーをマウスでさわる とプルダウンメニューが出る。コマンドモードで「u」(undo)を打つとソー ト前の状態に一瞬で復旧する。

ソートしたのはcsv形式データではない普通のテキストファイルである。約 5000行のなかに約1000行の空行があったため何も起こらなかったように見え たのである。vimは「:%!sort」コマンドの実行が終わったら、ソート結果 の冒頭部分(sort結果の第一行を最初の行として)を表示する。そこには約 1000行の空行が連続して並んでいる。相当にスクロールしないと文字部分が 現われない。

そこでソート結果の最初に文字が現われるはずの、逆順ソートを試してみ る。コマンドモードから「:%!sort /r」を実行する。しばらくの間(約2~10 秒)は現在の編集画面がそのままで、その後にソート結果の画面に置き換わ る。windows7のsortコマンドの後ろに付けたオプション「/r」は逆順ソート を指定している。

次に順方向ソートをもう一度試す。「:%!sort」を打ち込んだ直後に「G」 (shift-g、ファイルの最終行にジャンプ)を押してみる。こうすると、すぐ にsort結果が表示される。さらにvimエディタから離れて、windows7のコマ ンドプロンプトから「sort filename」や「sort /r filename」を実行して みる。エンターキーを押したらすぐにsortの結果が表示される。しばらくの 沈黙はwindows7のsortコマンドとvimエディタ間のデータ受け渡しの時間ら しい。

テキストファイルの空行は「:%s/^$//n」で数えられる。オプションの「n」 は、置換を実際には実行しないことを指定している。置換を実行しないが該 当個所数は表示される(vimは「置換すべき個所を検出しましたが、置換は実 行しませんでした」と報告してくる)。私が書く文章に、そのくらいの空行 があることは知っていたがsortを実行してみてその多さにあらためて驚いて しまう(空行が一箇所に集まると目立つ)。

私が書く文章は平均4行置きに空行を挟んでいることになる。一行が35文字 くらいなので140文字になる。あのtwitterが140字らしい。それと同じくら いの長さでつぶやいて(書いて)いるようだ。

エディタの一画面の全行が文字で埋まっていると読む気力が萎えてしまう。 原稿用紙に書くときは段落の最初の行で一字分だけ空ける(一字下げ)。一行 文字数は20字に固定されている。テキストエディタは、全角文字と半角文字 の混在や禁則処理により行末が揃わない(半角2文字くらいの凸凹はいっぱい 出来る)。そのため段落初めにおいて行頭の一字下げをしても、その強調効 果が薄れるように思える。

目視で段落区切りを検出するには段落初めの一字下げと一緒に段落終わりの スペース並び(空き)を見ている。行末が一直線に揃ってないと段落終わりを 見つけにくい。そこで一字下げをしないで、段落の前後に区切りとして空行 を挟み込むことにしている。そうすると文章の一塊が周りから浮き上がるよ うに感じられて読みやすい。

ホームページを閲覧するためのブラウザは日本語文の一字下げの段落区切り を理解してくれない。そのため改行タグの次に全角空白を入れるしかない。 ブラウザは連続スペースを一個のスペースにまとめてしまう。また、ブラウ ザは改行文字を一個のスペースで置き換える(改行タグのある場所が本当の 改行位置になる。画面右端での折り返し位置は画面幅で伸び縮みする)。ブ ラウザに表示された日本語文のなかに現われる不必要な半角空白は改行文字 かもしれない。全角空白は、全角幅の空きスペースをつくる特別な文字であ る。ブラウザは全角空白を二連続な半角スペースとして扱わない。半角文字 の2倍幅を持った真っ白の「顔なし」な一風変わった見慣れない文字とみ る。

改行タグの直後の全角空白はキッチリとした一字下げになる。それにより段 落初めは分かるけれど。段落間に空き行がなくてビッシリと詰まった長文を 読むのは疲れる。

行のソートが出来るようになってから技術評論社刊の「Vimテクニックバイ ブル」にある「テキスファイルをソートする」を読む。行のソートが「 :sort」で出来ると書いてある。sortの前に感嘆符を付けなくてもよいとい うことは、vim自体がsortコマンドを備えているということである(感嘆符は 外部コマンドを指定する)。「:help :sort」でヘルプが読める。外部コマン ドのsortに比べてvimが備えているsortコマンドのほうが指定を細かにでき る。まったくの「灯台下暗し」であった。vimのバージョン7以前は外部コマ ンドでソートしていたらしい。

vimの内部コマンドであるsortコマンドのほうが、vimにとっては外部コマン ドであるwindows7のsortコマンドを使うより速い。また、より細かい指定が できる。使い方を忘れたら「:help :sort」でヘルプが参照できる。 windowsのソートコマンドを使うなら、windowsのコマンドプロンプトから 「sort /?」でヘルプを読むことになる。

vi/vimやemacsは自前のソートコマンドを備えている。その他のテキストエ ディタになるとマクロとかプラグインなどの後付けでソートできるようにな るものが多いようだ。機能てんこ盛りで動きが遅くなるのは困るけれど後付 けの面倒がないのは嬉しい。デフォルトで付属している機能を使うほうが、 後付け(外付け)で入れた同様の機能を実現するものより操作がスムーズに行 なえる。

vimは、バージョン7からソートコマンドを備えたという。英文のスペル チェックもバージョン7から標準装備になっている。こちらも便利である。 タイプライター印字文書をpdfとしてホームページに掲載しているとか書籍 のページを画像としてpdfにしているもの、そして文章そのものの改変やコ ピーを拒否しているpdfなどは、手打ちでエディタに文章部分をコピーして いる。

その際に「:setl spell」でスペルチェックを有効にしておくとリアルタイ ムでチェックしてくれる。英単語の綴りを間違えたら単語の下に赤色で波形 なアンダーラインが現われる。エディタに訂正候補を表示させることもでき るが自分で正しい綴りに直しても誤り指摘のアンダーラインは消える。

vimのスペルチェックは日本語部分に対応していない。そもそもvimは日本語 の辞書を持っていないから当然である。日本語文は、英文のように単語間を 空白で区切る分かち書きをしない。そのため綴り間違いを検出するのが難し い。辞書を引くには、もとの文章を細切れに分解しなければならない。英文 は、書き下ろしたときからすでに単語間がスペースで区切られて分解が済ん でいる。日本語は、分かち書きに分解するひと手間が余計にかかる。なお、 日本語の中に英語が混在する場合は、それらの間がスペースで区切られてな いと英語部分もスペルミスと判定される。英単語の前後に空白がないと、日 本語部分を含む長大な英単語と誤解する。

ダ、ダーッと英文を打ち込んでから全文をスキャンして誤り個所を指摘する のではなくて、打ち込み途中にリアルタイムでスペルチェックしてくれる。 もとの英文を見ながらエディタに打ち込む(書き写し)のにとても便利であ る。

重装備なソフトでも快適に使いこなせるだけの高性能をパソコンが備えてき ている。ドエライ高機能なエディタであっても文字キーを押してから画面に その文字が表示されるまでに1秒もかかるようでは使い物にならない。vimの 以前のバージョンがソートやスペルチェックを備えてなかったのは機械(パ ソコン)性能による制約があったためかもしれない。

Vim version 7 introduced a :sort command. So if you're using v7 or later you can sort an entire file using :sort. If you're using an older version of Vim you'll need an external sort utility. Linux/UNIX users should already have sort installed. You can sort the entire file by executing :!%sort, which filters the file through the external sort utility.

| | コメント (6) | トラックバック (0)

« 2013年8月 | トップページ | 2013年10月 »