Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
UNIX 今日の技/実演vi
[go: Go Back, main page]

UNIX 今日の技/実演vi

実演 vi

UNIX 今日の技』の vi の操作に関連する項目を纏めたものです。 以下、vi と銘打ってますが、本当は vim です。 まあ、vim の方が高機能なだけで操作方法にあまり違いはありません。


メインエディタは秀丸@windows でも、UNIX 機に転送してしまったファイルを修正したい、ということはままあります。 そーゆー時に一度手元に転送して、修正して、転送するという手間は面倒ですね。 vi は POSIX で定義されており、標準的な UNIX 機なら入っていることが保証されています。 「ちょこっと修正」に vi を使えるようになったら便利ですよ。

POSIX
種々のUNIX間での互換性を確保するために策定された仕様セット。

はじめに

vi は「コマンドモード」と「入力モード」の2つのモードを利用します。 最初は以下の程度の認識から始めましょう。

  • コマンドモードはカーソルを移動するためのモード
  • コマンドモードで i を押せば入力モードに入る
  • 入力モードでタイプするとそのまま文字が入力される
  • 入力モードで [ESC] をタイプするとコマンドモードに戻る
  • コマンドモードで :w で保存、:q で vi を終了する

移動「h」「j」「k」「l」

  • h ←
  • j ↓
  • k ↑
  • l →

削除「x」「dd」

  • x 一文字削除
  • dd 一行削除

これだけ知ってたら最低限の編集はできますね? では、次回からはもっとラクチンに編集作業するための具体例を実演していきます。

INCAR ファイルを編集する

題材として、以下の INCARファイルを編集することを考えます。

# SCF input for VASP
# Note that VASP uses the FIRST occurence of a keyword
SYSTEM = Untitled (VASP)

    PREC = High
  IBRION = -1
     NSW = 0
   ENCUT = 400
    NELM = 40
  NELMIN = 2
   EDIFF = 1.0e-05
  EDIFFG = -0.02
 VOSKOWN = 1
  NBLOCK = 1
   ISPIN = 1
  INIWAV = 1
  ISTART = 0
  ICHARG = 2
   LWAVE = .FALSE.
  LCHARG = .FALSE.
  ISMEAR = 1
   SIGMA = 0.2
   IALGO = 48
   LREAL = .FALSE.

ENCUT を 500 にする

  • 「/ENCUT」 → 「l を数回」、あるいは「/400」で4の上にカーソルが来てる状態にする
  • s5[ESC]

検索「/」

コマンドモードで「/string」と打つと、カーソル位置以降で最初に string にマッチする部分までジャンプします。 vi では検索は、「探すため」というより「移動するため」によく使われます。

項目 ENCUT は INCAR 中で一回しか出てこないことが概ね保証されていますが、目的の値の部分にに行くまでに更に数回カーソル移動を繰り返さなければなりません。 今回の INCAR の例では 400 という文字列が他に出て来ないことが分かっているので、そのまま「/400」でジャンプする方がラクです。

順方向で検索を続ける場合はコマンドモードで「n」、逆方向では「N」です。 叩く度に次にマッチする部分にジャンプします。

なお、最後に行った検索ワードは常に記憶されているので、何らかの編集を行った後でも「n/N」 でジャンプできます。

削除して挿入「s」

今回の編集内容は「4→5」に書き換えるということでした。 ならば、4の上で「x→i→5」と打てば目的は達成できます。 しかしこの「削除して挿入」という操作は編集作業で非常によく行われる操作なので、vi では単独コマンドとして「s」に割当てられています。

私としては2キーコマンドが1キーになるだけで十分魅力的なんですが、他の人にはそれほど魅力的には映らないかもしれません。 「s」の威力は、「コマンドの回数を指定する」と組み合わせると最大限に発揮されます。 「コマンドの回数を指定する」は、また後日。

PREC から NELM までをコメントアウトする

  1. /PREC
  2. I#[ESC]
  3. j.j.j.j.

行頭に挿入「I」

カレント行の先頭にカーソルを移動し、その位置に文字を挿入します。

直前と同じ操作を実行「.」

おそらく、vi で最も便利なのはこの「.」です。 「.」は直前の操作と同じ操作を実行します。 例えば今回の例では「I#[ESC]」と等価になります。

勿論「I」以外にも使えます。 私がよく使うのは、「s(一文字削除&挿入)」「cw(単語削除&挿入)」です。

「=」という文字を 「>」に置換したい場合、以下のようにすることもできます。

  1. /=
  2. s>[ESC]
  3. n.n.n.n.

「FALSE」を「TRUE」に置換したい場合、以下のようにすることもできます。

  1. /FALSE
  2. cwTRUE[ESC]
  3. n.n.

ファイルの最後に「 NELECT = 446」の項目を追加する

  1. G
  2. o→「 NELECT = 446」

単位のジャンプ「G」

単純に「G」とした場合はファイルの末尾へジャンプします。

「G」の前に数字、例えば「12G」とした場合はファイルの12行目へジャンプします。

「gg」と小文字を2回打てば、ファイルの先頭へジャンプします。

新しい行を追加「o」「O」

カレント行の下に新しい行を追加して入力モードに移行します。

大文字「O」の場合は、カレント行の上に新しい行を追加します。 (すなわち、カレント行の先頭に改行を挿入し、その改行位置で入力モードとなる)

n回操作を繰り返す

例えば、60個のコメント文字でテキストを視覚的に区切りたいときどうします?

############################################################←こんなの

60数えながら「#」を打つのは嫌ですね。 あるいは、120行だけ下に移動したいとか。

vi ではコマンド入力の前に数字を打っておくと、その操作をその回数だけ繰り返します。 上記の目的は「60i#[ESC]」や[120j」で達成できます。 その他、既に紹介したコマンドでは以下のように使えます。

  • 「4s」4文字削除して入力モードに移行
  • 「2n」2つ先の検索ワードにジャンプ
  • 「3dd」3行削除
繰り返し?
厳密には「繰り返し」というより、コマンド毎に定義された処理をしています。例えば「32G」では「G」を32回繰り返すわけではありません。

undo「u」とredo「C-r」

undo は「u」、redo は「C-r」です。 「4u」のように回数を指定して遡ることもできます。

オリジナルviでのundo
オリジナル vi では undo は一段階だけで、2度目の「u」は redo になります。
vim
オリジナル vi に対する拡張版で、Vi IMprovement の略。今更言うのも何ですが、本記事では全て vim を想定しています。

一括置換「:%s/old/new/」

文字列の一括置換ができます。

  • 「:」の直後の「%」:「ファイルの全ての行で」という範囲指定
  • 「s」:「置換せよ」という命令
  • 「/old/new/」:「old という文字列を new に置換」という置換内容

「/old/new/」の部分は正規表現が効きます。 失敗しても「u」ですぐ戻せるので試行錯誤的にやっても無問題です。 細かいオプションがあったりするけど省略。

「%」の部分、細かい範囲指定をする場合は下記の『範囲指定「v」』を使うと便利です。

範囲指定「v」

操作に対して範囲を指定したい場合があります。

  • 10行3桁目〜20行12桁目までを削除/コピーしたい
  • この画面のココからココまで置換したい(けど行番号を調べるのが面倒)

範囲指定したい部分の先頭で「v」を打ってからカーソルを移動すると「今カーソルがいる地点まで」が範囲になります。 次に「v」を打つか「範囲に対応した編集」をするまでは範囲指定は有効なので、「検索によるジャンプ」や「行番号ジャンプ」など通常の移動手段は何でも使えます。

範囲指定してから、「d」だと削除、「y」だとコピー。 また、「:」を呼び出すと自動的に「:'<,'>」となっていて、これが「指定した範囲内で」という指示になります。 この範囲内で置換したい場合は「:'<,'>s/old/new/」です。

私は置換よりも、主に削除/コピーするのに使います。

行番号に対する指定
「:10,20s/old/new/」とすれば「10行目から20行目までで置換」というような「行単位での範囲指定」はできますが、桁指定はできません。

カット

「d」に続けて様々な指定ができますが、よく使うのは以下のようなところでしょう。

  • 「dd」 1行削除
  • 「3dd」 3行削除
  • 「dw」 1単語削除
  • 「d3w」 3単語削除
  • 「D」 カーソル位置から行末まで削除
  • 「v」で範囲指定してから「d」 指定範囲を削除

ヤンク(コピー)

「d」 を 「y」 に置き替えるとヤンク系の操作になります。

  • 「yy」 1行ヤンク
  • 「3yy」 3行ヤンク
  • 「yw」 1単語ヤンク
  • 「y3w」 3単語ヤンク
  • 「Y」 現在の行全てをヤンク(※「D」はカーソルから行末まで)
  • 「v」で範囲指定してから「y」 指定範囲をヤンク
ヤンク
「コピー」と言ってましたが、UNIX の世界ではバッファ(Windows でいうクリップボード?)に送ることを「ヤンク」と言います。

修正

「c」 を使えば修正系の操作になります。 これまででも「cw」は紹介しました。

  • 「cc」 1行削除して入力モード
  • 「3cc」 3行削除して入力モード
  • 「cw」 1単語削除して入力モード
  • 「c3w」 3単語削除して入力モード
  • 「C」 カーソル位置から行末まで削除して入力モード
  • 「v」で範囲指定してから「c」 指定範囲を削除して入力モード

ペースト「p」「P」

ヤンクバッファに蓄えられている文字列をペーストします。

複数のファイル(*/INCAR)の ENCUT を片っ端から「400→500」に修正する

複数のファイルを一気に修正して回りたい時は、コマンドラインから「vi */INCAR」のように呼びます。 こうすると複数のファイルを「順番に」編集できるようになります。 「同時に」ではありません。 各々は別個のファイルなんですから。

次のファイルに移るには「:n」ですが、その前に「:w」で保存しとかないと警告出して止められます。 「:w」「:n」 は「:wn」と一回で指定することもできます。 (前のファイルに戻る方法は私は知りません)

さて、こうやって連続して編集すると何がオイシイかと言うと、そのセッションの間は「検索文字」と「最後の編集」を覚えていてくれることです。 最初のファイルについて「/400」「r5」「:wn」してやったら、次のファイルは「n.:wn」で作業が終わります。 あとは「n.:wn」「n.:wn」……と最後のファイルが終わるまで繰り返せば良いだけです。

この手の「複数のファイルに対する編集作業」は、Emacs よりも断然 vi の方が速いです。 とゆーことで、vi で最も覚えるべきは以下の2つです。

  • 「/」「n」による移動
  • 「.」による「最後の編集を繰り返す」

これによってカーソルを目で追わなくても「移動→編集」をガシガシ行えます。 これ以外の編集作業は Emacs など他のエディタでやってもそんなに不便ではない(or そっちの方が便利)だったりします。 まあ起動が軽いので単発の編集でもよく使いますが。

一文字置換「r」

一文字削除して挿入「s」は既に紹介したのですが、挿入される文字が1文字であるならば、「r」を使うと最後に入力モードから抜けるために[ESC」を叩く手間が省けます。

less / more からの起動

less でテキストを眺めていて「あ、ここ修正したいな」みたいな場合、less上で「v」を押してやると vi を起動して編集できます。 vi を抜けると less は新しいファイルをリロードし、表示に反映します。

いやまあ環境変数 EDITOR に emacs を指定しておけば Emacs が起動するんですけどね。 でも Emacs は起動が重いので「ちょこっと修正」なら vi の方が便利かと思います。

単語の補完

入力モードで [C-p] すると、今打ちかけてる文字列と一致する単語を探して補完してくれます。 例えば、以下のようなファイルがあった場合、

nominal        名目上の
percolation    透過
perturb        動揺させる
precursor      先駆者、先駆物質
predominantly  大部分は
regime         領域
relevant       関連性のある(to)
residual       余りの
retrieve       救出する、回復する、検索する
scatter        散乱する
semantics      記号論、記号の意味
shallow        浅い

「i pre[C-p]」と打ってやると、precursor → predominantly と補完候補を探ってくれます。 逆方向に補完候補を戻るには [C-n] です。 C/C++ プログラミングでは、インクルードしているヘッダファイルを走査してそこで定義されている識別子からも補完してくれます。 C/C++ に限らず、プログラミングの場面で非常に強力です。

その他

これまで紹介したのよりは覚える必要性は低いかな、という項目を箇条書します。

  • カーソルの左に挿入する場合は「i」だが、カーソルの右に挿入する場合は「a」。これを知らないと行末に追加することができなかったりする。現在のカーソル位置によらず行末に追加する場合は「A」。
  • 行を連結して1行にするには「J」を使う。「10行連結」には「10J」。
  • その行の先頭にジャンプしたい時は「0」もしくは「^」、行末にジャンプしたい時は「$」。
  • 逆方向検索は、「/」ではなく、「?」。
  • 検索や置換には正規表現も指定できる。
  • 別のファイルを読み込める「:r filename」
  • シェルからコマンドを呼び出せる。例えば「:r! date」でテキスト中に現在時刻を入れることができる。
  • 何らかの理由で画面が乱れた場合、「C-l」で再描画する。
  • 「C-f」一画面下へ
  • 「C-b」一画面上へ
  • 「C-d」半画面下へ
  • 「C-u」半画面上へ
  • 「z.」カレント行が画面中央に来るようにスクロール

vi 本をさらうと知らないコマンドが幾つも出てきました。 まだ結構あるみたいですが、もう十分だと思いました。 もうおなかいっぱいです。

~/.vimrc

vi(vim)については既に書きましたが、今回は「オイシイ初期設定ファイルの作り方」です。

~ippei/.vimrc

岸田が現在使っている .vimrc です。 「"」以降がコメントになります。 「何ができるか」はコメント見れば大体分かりそうですね。

なお、map, imap 命令の行で使われている「^」は制御文字ですので、コピーするだけでは動きません。詳しくはまた後ほど。

"--- メモ ----------------------------------------------
" Windows で上手く行かない時は、環境変数 VIMRUNTIME をチェックする
"       VIMRUNTIME='D:\winProgram\vim-6.3.012-w32j\runtime'のように設定する
"### 入力モード時の操作
" C-u   入力モードに入ってから入力した全ての文字を削除(だけど邪魔)
" C-w   直前の単語を削除
" ←↓↑→      カーソルの移動、あちこちで入力できる!
" C-v   続けて打つ制御キーをそのまま入力(例:C-v C-l)
" C-[, C-c, C-3 端末にもよるが、ESC と同等
" C-o   一度だけコマンドモードのコマンドが打てる
"### その他
" 「どのキーを押しても全く反応が無い!!」→C-q(ウッカリC-sから復帰)
" U     行全体に行った変更を全て取り消し
" 範囲指定「3:」現在の行以下3行
" 「:%!expand」既に存在するタブ文字を空白文字に変更
" 「:%!unexpand」既に存在する連続する空白文字をタブ文字に変更
" 「>>」「<<」行をシフト。「5>>」とかで5行分実行とか
"入力モード中でC-d, C-t で行全体を左右にシフト

"参考リンク
"http://www15.ocn.ne.jp/~tusr/vim/options.html
"http://homepage1.nifty.com/niwatori/vi/
"--- Common options ----------------------------------------------
"set noerrorbells ruler notitle のように続けて書ける
" :set number? で そのオプションの設定状況を表示
" :set all で全てのオプションの設定状況を表示
" :set でデフォルトから変更されたオプションの設定状況を表示
" :mkvimrc で、現在のオプションを ~/.vimrc に書き出す(存在すれば無効)
" :source ~/.vimrc 拶 設定ファイルを読み直す
"set fexrc " *.c なファイルを読み込んだ時 ~/.vimrc.c があれば反映させる

set expandtab   " タブ文字の代わりに同じ幅の空白文字を入れる
set tabstop=2   " タブ文字の表示幅
"set list       " タブ文字、改行文字の表示
set listchars=eol:$,tab:>-  " list 表示の時の文字指定
set shiftwidth=2  " 「>>」,「<<」操作のシフト幅
"set autoindent  "ENTER 時に自動でインデント
"set smartindent "賢い自動インデント

set incsearch   " サーチをインクリメンタルサーチにする
"set smartcase  " 検索で大小文字を区別する
set ignorecase  " 検索で大小文字を区別しない
set wrapscan    " 検索でファイル終端に来たら先頭に戻る
set hlsearch    " 検索結果文字列のハイライト

set showmatch   " 入力時に対応する括弧を表示
"set wildmode=list  "補完動作の設定
set wildmenu    "補完候補を表示
set backspace=indent,eol,start "eol:改行,start:入力モードに入る前の文字
set encoding=japan  "vim が通常使用する文字エンコーディング
"set grepprg=search\ $*  ":grep で実行されるプログラム
set iminsert=0  "入力モードでのIMEのデフォルト状態
set imsearch=0  "検索モードでのIMEのデフォルト状態
set wrap      " 行末で折り返す
set ruler     " カーソル位置情報を表示
set shortmess+=I  "C-g で表示されるファイル情報のフォーマット
set showcmd     " 入力中のコマンドをステータスに表示
set laststatus=2  " ステータスラインを常に表示
set statusline=%<%f\ %m%r%h%w%{'['.(&fenc!=''?&fenc:&enc).']['.&ff.']'}%=%l,%c%V%8P
"↑ ステータスラインに文字コードと改行文字を表示する
set visualbell
"set tags+=../tags,../../tags   " タグファイル関連?
"set helpfile=/usr/local/text/vim.help  " ヘルプファイルの設定?
set nobackup    " バックアップファイルを作らない
"set number      " 行番号の表示
set title       " タイトルバーに編集中のファイル名などを表示
syntax on       " 構文を解釈してカラー表示

" キーマップの設定では行内はコメントできない
" ↓入力モードでのキーマップ
"   「^F」,「^[OC」は制御文字で、入力モードで「C-v C-f」「C-v →」で入力
imap ^F ^[OC
imap ^B ^[OD
imap ^W ^[:w^Ma
" ↑保存して入力モードに復帰(C-s でやりたいけど何故か C-v C-s で入らない)
imap ^U ^[
" ↑C-uを検出すると入力モードを抜ける(何もしない(C-uの無効化)にしたいんだけど)
imap ^E ^[:q^M

map ^W :w^M
map ^E :q^M
" 保存

" map ^A :set number^M
" ↑C-a で :set number を実行させる。制御コードで書く。
" 「map #6 /」のようにすると F6 キーで検索する
" imap ^B " (左矢印キー)
" ↑入力モードのキーマップ。入力モードでのカーソル移動
" cmap
" ↑: や / でコマンドラインにカーソルがあるときのキーマップ

if has("gui_win32") " Windows 環境ならば
  if filereadable( $HOME . "/.vimrc.windows" )
    source ~/.vimrc.windows
  endif
else
  if filereadable( $HOME . "/.vim/colors/ippei.vim" )
    colorscheme ippei
  endif
endif

タブ文字をどう扱うか?(expandtab, tabstop)

タブ文字は確かに便利なんですが、どのような状況でも最適なタブ幅というのが決定できないのが問題です。 プログラムのインデント幅としては2〜4文字が良いのですが、テーブルを組む場合には8文字でも足りないことがあります。

「*.c のファイルにはタブは2文字」、「*.dat では8文字」という場合分けをアプリケーションにさせることもできますが、こういうことさせると途端に煩雑になります。 というのも、そのテキストファイルを扱うのはエディタだけではないからです。 less や cat、grep などでもエディタでされるように表示されないと困る場面があります。 仮にテキストファイルを10種類に分類し、テキストファイルを扱うソフトウェアが10個あった場合には合計で100項目の設定をしなければならなくなります。

そういうわけで、私はテキストファイルにおけるタブ文字の使用を封印しています。 vim においては以下のような設定をしています。

set expandtab   " タブ文字の代わりに同じ幅の空白文字を入れる
set tabstop=2   " タブ文字の表示幅

オートインデント(autoindent, smartindent)

オートインデントは便利なんですが、マウスの中クリックでのペーストしたテキストがどんどん右にずれていくことがあります。 私は頻繁にこの操作を行うのでオートインデントはオフにしています。

「なんか良い解決法ないかなあ」と思っているのですが。

"set autoindent  "ENTER 時に自動でインデント
"set smartindent "賢い自動インデント

インクリメンタルサーチ(incsearch)

set incsearch   " サーチをインクリメンタルサーチにする

好みが分かれそうです。 通常のサーチでは

/string[ENTER]

と [ENTER] を打った所で実行するので、次の動作に滞りなく入れるのですが、 インクリメンタルサーチだと

/string

で「string」という文字列を打ち込んでいる最中もサーチが進みます。 この時によく [ENTER] を打ち忘れて hjkl でカーソル移動しようとして失敗してしまいます。

ですが、理性で考えると [ENTER] を入れる手間さえ忘れなければ、キー入力の総数は必ず通常サーチ以下になるので「こちらで慣れた方が便利な筈だ」、と自分に言い聞かせてインクリメンタルサーチを使っています。

検索結果のハイライト表示(hlsearch)

set hlsearch    " 検索結果文字列のハイライト

なお、vim での編集中にハイライトがうざくなった場合は、

:set nohlsearch

のコマンド入力でハイライト表示をやめることができます。

バックスペースを強化する(backspace)

デフォルトではバックスペースには様々な制限が加わっています。 backspace を設定することでそれを制御することができます。

set backspace=indent,eol,start "eol:改行,start:入力モードに入る前の文字

この設定では、「行頭の空白」「改行文字」「入力モードに入る前の文字」の削除を許可します。

キーマップ設定(map, imap, cmap)

vim には3種類のモードがあり、この各モードによってキーマップを設定するコマンドが異なります。

  • map コマンドモードのキーマップ
  • imap 入力モードのキーマップ
  • cmap コマンドラインにカーソルがあるときのキーマップ

なお、ここでの設定はキーコードを制御コードを用いてそのまま記述します。 例えば C-f と打った時の挙動を設定したいのならば、入力モードで「[C-v][C-f]」のように入力します。 [ESC] ならば「[C-v][ESC]」です。 (Emacs で入力するには [C-q] に続けて入力する)

以下、「^?」のように書かれている部分は全て制御コードです。

入力モードのキーマップ設定

imap ^W ^[:w^Ma
" ↑保存して入力モードに復帰

私はテキストを一行打つ間にも何度か保存するのが癖になっています。 「[ESC]:w[ENTER]a」 の作業が面倒なので、一つのキーバインドにまとめて快適に保存しています。

imap ^U ^[
" ↑C-uを検出すると入力モードを抜ける

[C-u] を打つと入力モードに入ってから打ち込んだ全ての文字が消えてしまいます。 こういう操作が欲しい場面もあるかもしれませんが、タイプミスで[C-u]を押してしまって一生懸命打ち込んだテキストがパーになることが私はよくあります。 ということで[C-u]にその元々の意味を失わせるために設定を上書きしています。

imap ^E ^[:q^M

[C-e]の1操作で編集を終了します。

windows の gvim でも同じ設定を使う

if has("gui_win32") " Windows 環境ならば
  if filereadable( $HOME . "/.vimrc.windows" )
    source ~/.vimrc.windows
  endif
else 
  if filereadable( $HOME . "/.vim/colors/ippei.vim" )
    colorscheme ippei
  endif
endif

環境に差がある部分だけを場合分けしています。

なお、Windows の .vimrc.windows にはフォント設定を入れています。

set guifont=MS_ゴシック:h9:cSHIFTJIS

これは文字コードの関係で(SJISで書かなければならない)別ファイルにしています。

vim の操作

入力モードで ←↓↑→

あちこちで入力できる!

……面白いんだけれど、普通にコマンドモードに抜けた方がアンドゥとかの操作がシンプルになって良いと思う。

コマンドライン入力のヒストリ

「:w」や「:%s/old/new/」の置換などの「:」で始まるコマンドは履歴が残ります。 「:」でコマンドライン入力の状態にしてから C-p で遡ることができます。 この履歴は、一度 vim を閉じても残ります。

私は「:%s/old/new/」のようなファイル全体を置換するコマンドを呼び出すのによく使います。

別ファイルの内容の読み込み(:r file)

「:r file」 で file という名前のファイルの内容をカーソル位置にペーストできます。 別ウィンドウを開かなくてもペースト操作できるので、慣れれば結構スマートな感じがします。

「:r」は「:read」の短縮形で、勿論「:read file」でも同様に動作します。 なお、「:w」は「:write」の、「:q」は「:quit」の短縮形です。

コマンドの実行結果をペースト(:r! command)

UNIX コマンドを実行した結果をペーストすることもできます。 岸田がよく使うのは以下のコマンドです。

  • 「:r! date」でテキストに日付を入れる
  • 「:r! pwd」で使い捨てスクリプトを書く時にディレクトリパスを入れる
  • 「:r! ls」でテキスト中にファイルリストを羅列する

「:r」の部分は先の「:read」と同じ意味です。 これに続く「!」はコマンドの実行を意味し、「:r!」で「コマンド実行した結果を読み込む」という意味になります。

コマンド実行部分はシェルが受け持つので、パイプや for 文なども使うことができます。 例えば、普段 zsh を使っている人は、

:r! for i in {1..100}; do ; echo $i; done

別のファイルの編集を始める(:e newfile)

「:e newfile」で現在編集しているファイルを離れて、newfile という名前の別ファイルの編集を新しく始めることができます。 (「:e」は「:edit」の短縮形)

現在のファイルの編集内容を破棄して移るには「:e! newfile」です。

最後にセーブした状態に復帰(:e!)

ファイル名を省略して「:e!」にすると最後にセーブした状態に復帰することができます。 「色々編集してみたけれどなんかしっくり来ないので編集結果を破棄したい」という場合、 勿論「:q!」で強制的に終了してもう一度開いたり、(vim ならば無制限にアンドゥができるので)「u」を押しまくっても良いのですが、「:e!」なら一手間でできます。

外部コマンドによる編集(:<範囲> ! コマンド)

テキスト形式で吐き出されるデータを整形しているときに、「部分的に外部コマンドを使いたい」と思うことはありませんか? 「sort したい」とか「3〜100行目を 'grep Li' したい」とか。 vi ではテキストを外部コマンドを使って編集する手段が用意されています。

:<範囲> ! コマンド 

まず範囲指定し、それに続けて「!」でコマンドを実行することを宣言、その後にコマンドを記述します。 動作としては、指定された範囲をストリームとしてパイプでコマンドに渡し、コマンドが標準出力に返すストリームを受け取って指定した範囲を置き換えます。

:% !sort -n +1 

原子が感じるポテンシャル(mkavepot.rb の出力)を欠陥からの距離でソートするのに役に立ちました。 (-n は数値順ソート、+1 は1番目の要素(左端の要素を0番目と数える)でソート)

:'<,'>!grep Li 

不要な行を削除するのにも使えそうです。

更新日時:Fri Dec 24 16:07:22 JST 2004
キーワード:
参照:[basics of unix for first principles calculation] [UNIX 今日の技]