こんにちは、ソーイ株式会社の髙﨑です。
私は業務で時々、Vimを使ってファイルを編集することがあります。
例えば、サーバー上のファイルを直接確認・修正するときなど、普段使っているエディタを使えない環境でVimを使うことがあります。
ただ、Vimを使うたびに操作方法やコマンドを調べ直しています。
「これ、前にも調べたはずなんだけどな……」と思いながら検索することも珍しくありません。
先日も、単語の中身だけを書き換えようとしてciwを打とうとしたのですが、ciまで打ったところで「このあと何だっけ」と手が止まってしまいました。
そこで改めてVimについて調べてみると、コマンドを一つずつ暗記するのではなく、「オペレータ」と「モーション」などを組み合わせて操作する考え方があることを知りました。
今回は、このVimの「文法」のようなものに注目して、自分なりに整理してみます。
Vimのコマンドをよく忘れてしまう方や、これからVimを使ってみたい方の参考になればと思います。
この記事の結論
Vimのノーマルモードの操作は、個別のコマンドとして覚えるだけでなく、「何をするか」と「どこまで操作するか」を組み合わせて考えると整理しやすくなります。
例えば、
-
d、c、y:何をするかを指定する「オペレータ」 -
w、b、$:カーソルをどこまで動かすかを指定する「モーション」 -
iw、i"、i(:文字列や記号の内側を指定する「テキストオブジェクト」
というように、それぞれに役割があります。
そのため、
d + w
ならdw、
d + 2 + w
ならd2wのように、覚えた要素を組み合わせて操作できます。
例えばdiwも、
d = 削除
iw = 単語の内側
と分けて考えられます。
「diwはこの操作」と丸暗記するのではなく、それぞれの記号が何を意味しているのかを知ることが、今回の記事のポイントです。
目次
なぜVimの操作を覚えられないのか
なぜVimの操作をなかなか覚えられないのか、自分なりに考えてみました。
まず、Vimを使う頻度がそれほど高くないことです。
業務でVimを使う機会はありますが、毎日Vimを使って作業しているわけではありません。
そのため、前回使ったときに覚えた操作も、次に使う頃には忘れてしまっています。
また、分からない操作があっても、その場で検索すれば解決できてしまいます。
ファイルを保存したいときに、「保存ってどうするんだっけ?」となっても、少し検索すればすぐに答えが見つかります。
操作を覚えていなくても作業自体は進められるので、「覚えないと困る」という状況になりにくいのです。
さらに、これまでVimのコマンドを「意味」ではなく、「操作方法」としてそのまま覚えようとしていました。
例えば、
dd = 1行削除
yy = 1行コピー
p = 貼り付け
というように、「この操作をするときはこのコマンド」と個別に覚えていました。
使用頻度が低い状態では、しばらく使わないだけですぐに忘れてしまいます。
そして、そもそも便利な操作を知らなかったことで、遠回りな操作をしていたこともありました。
以前、コピーの方法が分からなかったときは、コピーしたい内容を別の場所に手入力していました。
また、単語単位でカーソルを移動できることを知らなかった頃は、目的の場所までhやlを何度も押して、1文字ずつ移動していました。
そのときは「Vimだからこういうものなのかな」と思っていましたが、後からyyやp、wやbを知って、「こんなに簡単にできたのか」と驚きました。
こういう経験があって、単にコマンドを覚えるよりも、「Vimの操作ってどういうルールで組み立てられているんだろう」と考えるようになりました。
Vimの基本操作を整理する
Vimのコマンドを見ていく前に、まずは基本的な操作を整理します。
モード
Vimを使い始めて最初に戸惑ったのが、「モード」という考え方です。
普段使っているテキストエディタなら、ファイルを開いたらそのまま文字を入力できます。
一方、Vimでは現在どのモードにいるかによって、キーボードを押したときの動作が変わります。
基本的には、文字を入力するための「インサートモード」と、ファイル内を移動したりコマンドを実行したりする「ノーマルモード」を使い分けます。
例えば、ノーマルモードでiを押すとインサートモードに切り替わり、文字を入力できるようになります。
入力が終わったらEscを押して、ノーマルモードに戻ります。
Vimを使い始めた頃は、「文字を入力したいのに入力できない」となって、現在のモードを確認することもありました。
保存と終了
ファイルの保存や終了にもVim独自の操作があります。
カーソル移動
ノーマルモードでは、カーソル移動にh、j、k、lを使えます。
また、単語単位で移動するためのwやbなどもあります。
このように、Vimには普段使っているエディタとは違う操作がいくつもあります。
最初からすべて覚えようとすると大変なので、まずはモードや基本的な移動方法を覚えて、そこから少しずつ操作を増やしていくほうが自分には合っていそうです。
Vimコマンドの文法を理解する
ここが今回一番整理したかった部分です。
これまで私は、
dd = 1行削除
dw = 単語を削除
diw = 単語の中身を削除
というように、操作とコマンドを1対1で覚えていました。
しかし、Vimのノーマルモードには、コマンドを組み合わせて操作を作るための考え方があります。
オペレータとモーション
Vimの操作は、基本的に、
オペレータ + モーション
という形で考えることができます。
より一般化すると、
{オペレータ}{カウント}{モーション または テキストオブジェクト}
という構造になります。
Vimの公式ドキュメントでも、オペレータの後にモーションを続けることで、モーションによって移動した範囲にオペレータを適用できる、と説明されています。
例えばd4wなら、dという削除オペレータと4wという移動を組み合わせて、4単語分を削除できます。
それぞれの役割を簡単に整理すると、次のようになります。
| 種類 | 役割 | 例 |
|---|---|---|
| オペレータ | 何をするか |
d 削除、c 変更、y ヤンク |
| カウント | 何回・どの程度行うか |
2、3など |
| モーション | カーソルをどこまで動かすか |
w、b、$など |
| テキストオブジェクト | どの範囲を対象にするか |
iw、i"、i(など |
例えば、
d + w
なら、
d = 削除
w = 次の単語へ移動
なので、dwはカーソル位置から次の単語の開始位置までを削除する操作になります。
さらに、
d + 2 + w
と組み合わせれば、
d2w
となります。
dwとd2wを別々のコマンドとして覚えるのではなく、「削除する」というオペレータに「どこまで」というモーションを組み合わせる、と考えるわけです。
この考え方を知っておくと、今まで知らなかった組み合わせも少し考えやすくなります。
テキストオブジェクト
Vimには、モーションとは少し違う「テキストオブジェクト」という考え方もあります。
例えば、
iw
i"
i(
などです。
iはInner、つまり「内側」を表します。
テキストオブジェクトは、カーソルの位置から移動した範囲ではなく、カーソルが含まれている単語や括弧などを一つのまとまりとして指定できます。
例えば、
"hello world"
という文字列の中にカーソルがある場合、
di"
とすると、ダブルクォートの内側を削除できます。
また、
(user_name)
のような文字列に対して、
di(
とすると、括弧の内側を削除できます。
これも、
d + iw
d + i"
d + i(
と分けて考えることができます。
つまり、
d = 削除
i = 内側
w / " / ( = 対象
ということです。
この考え方を知ってから、Vimのコマンドが以前より少し整理しやすくなりました。
実際の編集操作で確認する
Vimの操作は、カーソル位置によって結果が変わります。
そのため、ここでは実際の編集前と編集後を並べて確認してみます。
今回の動作確認は、Vim 9.2のノーマルモードで行いました。
|はカーソル位置を表しています。
dwで単語を削除する
まずはdwです。
操作前:
user |name list
ここで、
dw
と入力します。
操作後:
user |list
dwでは、カーソル位置から次の単語の開始位置までが削除されます。
そのため、nameだけでなく、その後ろの空白も削除されています。
つまり、
d + w
で、
削除 + 次の単語まで移動
という操作です。
diwで単語そのものを削除する
次にdiwです。
操作前:
user |name list
ここで、
diw
と入力します。
操作後:
user | list
diwでは、カーソルが含まれている単語そのものを対象にします。
iwは「inner word」を表し、単語の内側を対象にします。
そのため、dwとは異なり、単語の後ろにある空白は残ります。
dwでは、
name_
のように単語と後ろの空白まで削除されます。
一方、diwでは、
name
だけが削除されます。
実際の編集結果を並べてみると、dwとdiwの違いも分かりやすいと思います。
d2wで2単語分を削除する
次に、カウントを組み合わせてみます。
操作前:
one |two three four
ここで、
d2w
と入力します。
操作後:
one |four
これは、
d + 2 + w
と考えることができます。
d = 削除
2 = 2回
w = 次の単語へ移動
という組み合わせです。
dwを覚えたあとに「2単語分削除したい」となったら、2を組み合わせてd2wと考えることができます。
di"でクォート内を削除する
テキストオブジェクトを使った例も見てみます。
操作前:
name = "|Takasaki"
カーソルはダブルクォートの中にあるものとします。
ここで、
di"
と入力します。
操作後:
name = "|"
di"は、
d + i"
と分けて考えられます。
d = 削除
i" = ダブルクォートの内側
そのため、「ダブルクォートの中身を削除したい」と考えたときに、di"というコマンドを丸暗記していなくても、組み合わせから考えられます。
ci"でクォート内を書き換える
同じように、変更もできます。
操作前:
name = "|Takasaki"
ここで、
ci"
と入力すると、ダブルクォートの内側が削除され、インサートモードになります。
例えば、そのまま、
Suzuki
と入力してEscを押すと、
操作後:
name = "Suzuki"
となります。
これも、
c + i"
と考えれば、
c = 変更
i" = ダブルクォートの内側
という組み合わせです。
実際にこうして並べてみると、Vimのコマンドは「記号を覚える」というより、「何をするか」と「どこを対象にするか」を組み合わせて考えたほうが覚えやすそうです。
cwには注意が必要
ここまで、
オペレータ + モーション
という考え方でコマンドを整理してきました。
ただし、ここには注意点があります。
cwは、単純に「c + wだからdwと同じ範囲を変更する」と考えることはできません。
Vimでは、cwには特別な挙動があります。
通常、単語の途中にカーソルがある場合、cwはceと同じ範囲を変更します。
Vimの公式ドキュメントでも、cwとcWは単語の後ろの空白を含まず、単語の末尾まで変更する特例として説明されています。
例えば、
操作前:
hello |world foo
ここで、
dw
を実行すると、
hello |foo
となります。
一方、
cw
でnewと入力すると、
hello new| foo
となります。
このように、dwではworldの後ろの空白も削除されるのに対して、cwではworldだけが変更され、後ろの空白は残ります。
つまり、
dw
と
cw
は、どちらもdやcとwを組み合わせた操作ですが、cwには特別なルールがあります。
そのため、
オペレータ + モーション
という考え方は便利ですが、すべての組み合わせが完全に同じ規則で動くわけではありません。
cwのような例外もあるので、基本的なルールを知ったうえで、実際に動かして確認することも大切です。
よく使うVimコマンドを整理する
ここまでの内容をもとに、普段の作業で使いそうなコマンドを整理してみます。
| 分類 | コマンド | 内容 |
|---|---|---|
| 移動 |
h j k l
|
左・下・上・右へ移動 |
| 移動 | w |
次の単語へ移動 |
| 移動 | b |
前の単語へ移動 |
| 移動 | 0 |
行の先頭へ移動 |
| 移動 | $ |
行の末尾へ移動 |
| 削除 | dd |
1行削除 |
| 削除 | dw |
カーソル位置から次の単語の開始位置まで削除 |
| 削除 | diw |
カーソル位置の単語を削除 |
| 削除 | di" |
ダブルクォートの内側を削除 |
| コピー | yy |
1行をヤンク |
| 貼り付け | p |
貼り付け |
| 変更 | cw |
単語を変更 |
| 変更 | ciw |
カーソル位置の単語を変更 |
| Undo | u |
操作を元に戻す |
| 検索 | / |
文字列を検索 |
こうして見ると、以前のように、
diw = 単語の中身を削除
ciw = 単語の中身を変更
と一つずつ覚えなくてもよさそうです。
例えば、
d = 削除
c = 変更
i = 内側
w = 単語
と覚えておけば、
diw
ciw
を組み立てて考えられます。
さらに、
d + 2 + w
なら、
d2w
と考えられます。
もちろん、すべてのコマンドをその場で思いつけるわけではありません。
私自身も今後も検索すると思います。
それでも、「まったく手がかりがない状態」から、
「dで削除して、あとは対象を指定するんだったな」
と考えられるようになっただけでも、以前より覚えやすくなったと感じています。
まとめ
今回は、Vimのコマンドを丸暗記するのではなく、オペレータとモーション、テキストオブジェクトの組み合わせとして考える方法を整理しました。
これまで私は、
dw = 単語を削除
diw = 単語の内側を削除
ciw = 単語の内側を変更
というように、操作ごとに覚えていました。
しかし、
d = 削除
c = 変更
w = 単語への移動
i = 内側
という役割を知っておけば、
dw
diw
ciw
d2w
ci"
di(
のような操作を、組み合わせとして考えられます。
特に今回、自分が以前していた「コピーしたい内容を手入力する」「hやlで1文字ずつ移動する」といった操作を振り返ってみて、Vimの操作を知らないこと自体が、作業の遠回りにつながっていたと感じました。
一方で、今回整理したからといって、すべてのコマンドを覚えられたわけではありません。
ciまで入力して「このあと何だっけ?」となることも、まだあります。
それでも、以前のように何も分からない状態で検索するのではなく、
「cは変更だから、あとは対象を指定するんだったな」
と考えられるようになったのは、自分にとって大きな変化でした。
Vimはコマンドが多いので、全部覚えようとするとやっぱり大変です。
まずはdやc、wやiなど、よく使うものだけ覚えておいて、必要になったら組み合わせを考えるくらいでいいのかなと思っています。
今後も実際の業務でVimを使いながら、「知らなかった操作」を少しずつ減らしていきたいと思います。
同じようにVimの操作をよく忘れてしまう方や、これからVimを使ってみたい方の参考になれば幸いです。
参考記事
- Vim日本語ドキュメント - usr_04
- Vim日本語ドキュメント - motion
- Vim日本語ドキュメント - change
- Vimのコマンドの表記とコマンドの基本構造(オペレーターとモーション)
お知らせ
技術ブログを週1〜2本更新中、ソーイをフォローして最新記事をチェック!
https://qiita.com/organizations/sewii


