外部のフィルタプログラムの利用

機能拡張の感覚でテキストフィルタに通す

概要

Vi(JVim)には,指定した範囲を外部のフィルタプログラムの入力として渡して 得られた出力と置き換えることが簡単にできます. この機能の使い方を解説します

外部のプログラム利用の基礎知識

まず,例として sort コマンドを使ってみましょう. 簡単に sort について 説明すると,与えられた複数の行を「並べかえる」コマンドです
いくつか使用例をあげて実際の使い方を示します

例 1

!Lsort とすれば「カーソル行から表示されている画面の最下行までの 範囲にある行を」並びかえます. つまり,

!(カーソル移動形式の範囲指定)(外部のコマンド名)

という形式です

例 2

5!!sort とすれば「カーソルの行を含めて 後ろに5行分の範囲を」並びかえ ます. つまり

(行数)!!(外部のコマンド名)

という形式です

例 3

もちろん,Exコマンドで使えるような範囲の指定方法を使って

:(範囲)!(外部のコマンド名)

というように使えます


(外部のコマンド名)の部分には

5!!sort -nr

のように"sort"コマンドのオプションも書けますし

5!!sort -nr | uniq

のようにパイプを使って二つ以上のコマンドを同時に通すことも可能です

このように 外部のコマンドを機能の一部のような感覚で使える ので 普段使い慣れたフィルタの細かい挙動や細かいオプションの指定などをそのまま 編集の時に生かせます
他の「高機能な」エディタなどでは様々な機能を自前で持っていることが多いですが, 新しくその機能の細かい挙動などに慣れたりカスタマイズする手間があったり 組み込みの機能に不満があっても我慢しなければなりません. JVimでは, 自分の好きな 挙動をするコマンドを呼び出すだけですから, このような不満は出ないし, (例えばソート 機能ならば)自分の好みに最も合ったsortコマンドを探して取り換えたり,プログラムを 改造したりして使いやすくもできます

範囲の指定に困ったら

広くて見通せない範囲をコマンドに通したい場合や,すぐには行数や移動コマンドが 思い付かないような範囲を指定したい場合は,次のような方法がお勧めです

例 4

範囲の開始としたい行に移動してから, ma などと マークをつけて から, 範囲の 終端としたい行に移動して :'a,.!(外部コマンド名) という指定が 手軽で簡単です

例 5

Visual範囲指定を使って

(Visual範囲指定をしてから)!(外部のコマンド名)

という形式でも使えます

別文章「行範囲のいろいろな指定方法」に書いた指定方法は,どれでも使えますので そちらも参照して下さい
「同じコマンドの繰り返し」も便利です. : だけ打ってから CTRL-P を 押すごとに過去に実行したコマンドが, 次々とよみがえります

"=" コマンドについて

よく使う外部のフィルタプログラムについては いちいちコマンド名を打たなくても 設定に 登録 しておいて,あたかもJVimの機能のように使えます. コマンド = は「任意のあらかじめ指定されている外部のフィルタプログラムに通す」 というものです. 初期設定( $HOME/.vimrc など)に

set equalprg=sort

のように書いておくと,コマンド =を使った時に, sort に通すようにできます
実際に使う時は,削除やYankコマンドと同じような要領で,カーソル移動コマンドを 後ろにつけて操作対象範囲を指定します. つまり =H ならば「カーソルのある行と表示画面の一番上の行の間の範囲を」sortするし 5== ならば「カーソルのある行以下5行を」並びかえます. また, [Visual範囲指定をしてから]= のような形式でも使えます

オプションをつけたりパイプを使って複数のコマンドに通したい時は

set equalprg=sort\ -nr\ \|\ uniq

のように特殊文字や空白をバックスラッシュでエスケープする必要があります
この例ならば sort -nr | uniq に通すことになります

コマンド = に割り当てできるのは一種類だけですので,使用頻度の高いものを登録 しておきたいものです

"sort"コマンド使用例

ここからは,実際のコマンドの使用例を書きます
外部コマンドを使うのですから, OSや機種やバージョンの違いによって, sort の 仕様(オプションとか制限とか)も,いろいろ違うでしょうけど,多くの機種などでは

:%!sort -r

で,「ファイルすべての行を対象として逆順にソート」します

:%!sort -nr

オプション -n は「数字を数値の順番としてソート」という意味なので -nr だと「数値の逆順ソート」という意味です

また,表のように明確にスペースやタブなどで区切られている行の場合に

:'a,'b!sort +2

のようにすると「マーク"a"から"b"までの行」範囲を 「先頭から三番目の単語を対象としてソート」のように使えます

外部のコマンドが簡単に使えると, その外部コマンドについて 知れば知るほど,JVimも楽に便利に使えるようになるというわけなのですから それぞれの コマンドのマニュアルなどは良く読みましょう

"uniq"コマンド使用例

特別な意図で整形された文章などは,空白行の連続がたくさん入っているものがあって 読みにくいものがあります. こんな時には普通の正規表現とdコマンドの組合せで 連続した空行を一行にまとめることもできますが, uniq を使うのも悪くないですね

:%!uniq

と打つだけです. また, sort と組み合わせて使うことも多いですよね

"cat"コマンド使用例

普通, cat は読み込んだ内容をそのまま出力するので使っても意味がないと思うかも 知れませんが,よくマニュアルを読んでみると意外とオプションが多いコマンドです. 例えば

10!!cat -n

とすれば,カーソル以下の10行の先頭に通し番号をつけることができます. 一行づつの 箇条書きに番号をつけたり,ちょっとしたリスト形式として使えます

"nkf"コマンド使用例

nkf は,文字コード変換コマンドとして結構有名ですが,文字コードの変換機能なら JVimが自前でもっているので外部プログラムのお世話になることもないです. でも nkf には,他にも様々な便利な機能があるのです. 是非インストールすべき コマンドだと思います

まず,このコマンドは, MIMEエンコードされた文字列を解読できる ので,メール のSubject部分などを普通の文章に戻すのに使えます. エンコードされた行で

!!nkf -m

とか,あるいは複数行に渡っているなら 3!!nkf -m などと打てば解読できます

Base64 の解読もできます. V コマンドなどで範囲指定してから :5,40!nkf -mB などとします

また, -f オプションで,一行の長さを指定して簡単な 桁折り整形 もできます. たとえば

{!}nkf -f70

などとして,カーソルのある段落全体を幅70で整形したりできます. これは,すっごく便利です

-r オプションでは, rot13による簡単な暗号化 (?)ができます. :%!nkf -r で,ファイル全体を処理できます.解読も同じ操作です. rot13なんて,暗号とは言えない程度の 簡単なフィルタ処理なのですが,「ちょっと目に触れられる文章を簡単に隠せる」ので 便利ではあります. 他にも機能があります. 詳しくは nkf のマニュアルを見て下さい

"expand"と"unexpand"コマンド

タブを数個の空白に変換してくれるコマンドです
:%!expand でタブはスペース文字になり :%!unexpand で スペース文字の連続がタブに変換されます

"kakasi"コマンド使用例

実用かどうかは知りませんが… kakasi というコマンドは,漢字,ひらがな,カタカナの 変換ソフトとして意外と多くのマシンに密かに(?)インストールされていたりします
日本語の漢字が含まれている文章で :%!kakasi -JH -KH などとして遊べます

自作のスクリプトを書く例

既存のフィルタプログラムだけでなく,もちろん自分でフィルタとして動作する プログラムやスクリプトを書いて使っても(もちろん)OKです
各種の整形,並び替え,暗号化,変換処理など…自分の好きな処理をどんどん書いて 便利に使いましょう

簡単な具体例を書きます
例えば,次のたった二行だけのRubyのスクリプトならば

#!/usr/local/bin/ruby -n
print " (#{$.}) #{$_}"

行頭に括弧つきの行番号を入れるだけですが,もちろん動作します
まぁ,あまり簡単なものなら 単なる置換えコマンドを(mapなどして)使うという手段も ありますが,外部のコマンドにするならば,どんなに複雑な処理でも思いのままですね

perlでもsedでもシェルスクリプトでも,もちろんC言語などでも自分の好みの言語が 使えるし,作成したスクリプトやプログラムは,JVimの拡張機能のようにして使う以外に 単体で通常のフィルタプログラムとして使えるのがうれしいですね


前項目, 「行範囲のいろいろな指定方法」へ

目次へ

次項目, 「外部のプログラムの利用で機能拡張」へ