第11章 viエディタの基本操作(vi使い方)

LPIC-1 103.8 相当

サーバー環境には必ずと言っていいほど入っている、伝統的なテキストエディタ vi(多くの環境では高機能版の vim)の基本的な使い方を扱います。LPIC-1でも出題範囲に含まれています。

viの3つのモード

viの最大の特徴は、操作対象によって「モード」を切り替える設計になっていることです。最初は戸惑いますが、慣れると効率よく編集できます。GUIのエディタのようにマウスでカーソルを動かしたりメニューを選んだりする代わりに、キーボードから手を離さずすべての操作を完結できるのが最大の利点で、SSH接続先のサーバーでGUIが使えない状況でも変わらず編集作業ができます。

モード役割入り方
ノーマルモードカーソル移動・削除・コピーなどのコマンド実行(起動直後はこのモード)Escキーでいつでも戻れる
挿入モード実際に文字を入力するノーマルモードで i や a など
コマンドラインモード保存・終了・検索などノーマルモードで :
ビジュアルモード(vim拡張)文字・行・矩形範囲を選択してからコマンドを適用するノーマルモードで v(文字単位)・V(行単位)

viの起動方法もいくつかあります。vi ファイル名で開くと、既存のファイルなら内容を読み込んで編集を開始し、存在しないファイル名なら新規作成として扱われます(実際に保存するまではディスク上にファイルは作られません)。

$ vi memo.txt        # 既存ファイルを開く、なければ新規作成の準備
$ vi +10 memo.txt     # 10行目にカーソルを合わせた状態で開く
$ vi +/keyword memo.txt # keywordが最初に見つかった行にカーソルを合わせて開く

ノーマルモードの基本操作

キー動作
iカーソル位置の前から挿入モードへ
aカーソル位置の後から挿入モードへ
oカーソル行の下に新しい行を挿入して挿入モードへ
Oカーソル行の上に新しい行を挿入して挿入モードへ
dd1行削除(切り取り)
yy1行コピー(ヤンク)
p直前に削除・コピーした内容を貼り付け
xカーソル位置の1文字を削除
u直前の操作を取り消す(undo)
Ctrl+rundoで取り消した操作をやり直す(redo)
/検索語文字列を検索

ddやyyには、前に数字を付けて回数を指定できます。例えば3ddはカーソル行を含めて3行を削除し、5yyは5行をまとめてコピーします。この「数字+コマンド」という組み合わせはviの多くの操作に共通するルールで、カーソル移動コマンドと組み合わせてd3j(下方向に3行分削除)のような使い方もできます。

ビジュアルモードでの範囲選択

vim(多くのLinuxディストリビューションでviとして使われている高機能版)ではビジュアルモードを使うと、削除やコピーの対象範囲を画面で確認しながら選択できます。

操作動作
v でカーソル移動文字単位で範囲を選択
V でカーソル移動行単位で範囲を選択
選択後に d選択範囲を削除
選択後に y選択範囲をヤンク(コピー)

コマンドラインモードの基本操作

コマンド動作
:w保存(write)
:w ファイル名指定した別名で保存(元のファイルはそのまま)
:q終了(quit)。未保存の変更があるとエラーになる
:wq または :x保存して終了
:q!変更を破棄して強制終了
:wq!読み取り専用ファイルなどに強制的に保存して終了(権限があれば)

:wqと:xは似ていますが厳密には少し違いがあります。:wqは変更の有無にかかわらず必ず保存してから終了しますが、:xはファイルに変更が加えられていなければ保存処理自体を省略して終了します。日常的にはどちらを使っても困ることはほとんどありません。

覚え方のコツ: 迷ったら Esc を押してノーマルモードに戻る、という習慣をつけると混乱しにくくなります。また :w(write=書く)、:q(quit=終わる)のように、コマンドの由来になった英単語を意識すると暗記しやすくなります。

カーソル移動の基本

キー動作
h j k l左・下・上・右へ1文字(1行)移動
w次の単語の先頭へ移動
b前の単語の先頭へ移動
0行の先頭へ移動
$行の末尾へ移動
ggファイルの先頭へ移動
Gファイルの末尾へ移動
:数字指定した行番号へ移動(例: :10で10行目へ)
Ctrl+f / Ctrl+b画面単位で1ページ分だけ下・上にスクロール

移動系のコマンドにも数字を前置できます。5Gや5ggは5行目へジャンプし、3wは次の単語へ3回分(=3単語分)カーソルを進めます。大きなファイルの中を素早く移動する際に役立つテクニックです。

コマンドラインモードでの検索・置換

コマンドラインモードでは、ファイル全体に対する一括置換も行えます。sedの書式と似ています。

:%s/foo/bar/g       # ファイル全体でfooをbarに置換
3 substitutions on 3 lines
:%s/foo/bar/gc      # 置換ごとに確認を求める(c=confirm)
replace with bar (y/n/a/q/l/^E/^Y)?
:5,10s/foo/bar/g    # 5〜10行目だけを対象に置換
2 substitutions on 2 lines
:.,$s/foo/bar/g     # カーソル行から末尾までを対象に置換(.は現在行、$は最終行)
1 substitution on 1 line
:set number         # 行番号を表示
:set nonumber       # 行番号表示を解除
:noh                # 検索によるハイライトを解除

この行のこの値に注目: 置換系のコマンドを実行すると、画面下部のステータス行に◯ substitutions on ◯ linesという完了報告が表示され、実際に何件置換されたかをその場で確認できます。gc付きの場合は1件ごとにreplace with bar (y/n/...)?という確認が挟まり、yで置換、nでスキップ、aで残り全部を確認なしに置換、といった選択ができます。

ノーマルモードでの/検索語の後、nキーで次の一致箇所へ、Nキーで前の一致箇所へジャンプできます。/がカーソルより下方向を検索するのに対し、?検索語はカーソルより上方向を検索します。検索語には正規表現も使えるため、/^#のようにすれば「#で始まる行」を検索できます。

複数ファイルの同時編集

viは1つのセッションで複数のファイルを開き、切り替えながら編集することもできます。

$ vi file1.txt file2.txt   # 2つのファイルを指定して起動
コマンド動作
:n次に指定したファイルへ切り替え
:prev前のファイルへ切り替え
:sp ファイル名画面を水平分割して別ファイルを開く(vim拡張)
よくあるつまずき: viは起動直後がノーマルモードです。何もせずいきなり文字を入力すると、iやxなどのコマンドとして解釈されてファイルが意図せず変更されてしまいます。編集を始める前に必ずiなどでモードを確認する習慣をつけましょう。特にコマンドラインモードのつもりで:を押し忘れたまま数字を入力すると、カーソル移動の回数指定として解釈されてしまうため注意が必要です。
試験対策: LPIC-1では、viの基本操作コマンド(i, a, dd, yy, p, :wq, :q!など)の意味を問う問題が定番です。実機で実際に手を動かして体で覚えるのが最も確実な対策になります。

なぜサーバー管理者はviから逃れられないのか

操作体系が独特で最初はとっつきにくいviですが、それでも学ぶ価値があるのには理由があります。最小構成のLinuxサーバーやレスキューモードでは、GUIエディタはもちろん、nanoすら入っていないことがある一方で、viはPOSIX標準で規定されたエディタのため、ほぼすべてのLinux/Unix系システムに標準で搭載されています。「このサーバーには使い慣れたエディタが入っていない」という状況に陥っても、viだけはほぼ確実に使えるという安心感は、現場で長く使われ続けている大きな理由の一つです。最初はコマンドを都度調べながらでも構わないので、最低限「編集して保存する」までの流れだけは体に染み込ませておくと安心です。

補足: vimでは~/.vimrcに設定を書いておくと、起動のたびに好みの挙動を反映できます。例えば set number を書いておけば毎回:set numberと打たなくても行番号が表示された状態で開けます。サーバー作業で頻繁にviを使うようになったら、少しずつ自分用の設定を育てていくとよいでしょう。

確認クイズ

Q1. viで文字を入力するために切り替える必要があるモードはどれですか?

解説: 実際に文字を入力するには挿入モードに切り替える必要があります。ノーマルモードで i や a を押すことで入ります。

Q2. 編集内容を保存せずにviを強制終了するコマンドはどれですか?

解説: :q! は変更を保存せずに強制的に終了するコマンドです。:wqは保存して終了、:wは保存のみです。

Q3. ノーマルモードでカーソル行を1行削除(切り取り)するコマンドはどれですか?

解説: ddは1行削除(切り取り)のコマンドです。yyはコピー(ヤンク)、pは貼り付けです。

Q4. 挿入モードやコマンドラインモードから、ノーマルモードに戻るキーはどれですか?

解説: Escキーを押すことで、どのモードからでもノーマルモードに戻ることができます。