Vimで置換する4つの方法と使い分け
Vimには「今いる行の一部を書き換える」だけでも複数のやり方があります。最初はどれか1つを覚えて満足しますが、場面によって向き不向きがあるので、4つとも知っておいて損はありません。
目次(11項目)
| キー | これだけ覚える |
|---|---|
| R | 置換モード。同じ文字数の上書きに |
:s/置換前/置換後/ | ファイル全体・複数行の一括置換 |
| ciw | 単語単位ですばやく書き換え |
| . | 直前の変更を繰り返す |
1. 置換モード(R)
R{変更後のテキスト}
対象の位置に移動してRを押すと置換モードに入り、上書きで文字を打ち込めます。初心者が最初に覚えやすい方法ですが、置換前後で文字数が変わる編集には向きません。
let value = 100;
let value = 200;
文字数が同じ書き換えに限定される点が弱点です。桁数が変わる書き換えでは、余分な文字が残ったり足りなくなったりします。
2. 置換コマンド(:substitute)
:s/置換前/置換後/
他のエディタでもおなじみの置換コマンドです。gフラグで行内の複数箇所を一括置換、cフラグで確認しながら置換できます。ファイル全体や複数行にまたがる置換には非常に強力ですが、1行のちょっとした書き換えに使うにはタイプ数が多くなります。
3. ビジュアルモード+オペレータ
v{範囲を選択}c
ビジュアルモードで範囲を選択してからcで変更します。矩形選択したいときはCtrl-vを使います。選択した範囲がそのまま見えるので直感的ですが、範囲指定のたびにカーソルを動かす手間があり、同じ操作を繰り返す用途にはやや不向きです。
4. オペレータ+モーション/テキストオブジェクト
cw " 単語の頭にいる場合
ciw " 単語のどこにいてもよい場合
移動を最小限にして、範囲指定と変更を1つのコマンドで済ませる方法です。tやfで素早く目的の位置まで移動し、そこからcwやciwで書き換える、という流れが定番になります。cwとciwの使い分けは別記事で詳しく扱っています。
同じ書き換えを繰り返すなら . と組み合わせる
どの方法を選んだ場合でも、同じ変更を別の場所にも繰り返したいなら.(ドットコマンド)が効きます。ciwで単語を書き換えたあと、次の対象へtやfで移動して.を押すだけで、直前と同じ変更を再現できます。置換コマンドの:sはパターンマッチなので繰り返しに強いですが、単発の書き換えを複数箇所に展開したいときはciw系と.の組み合わせのほうが手数が少ないことが多くあります。
どれを選べばいいか
| 状況 | おすすめ |
|---|---|
| 同じ文字数で単純に上書き | 置換モード(R) |
| ファイル全体・複数行の一括置換 | 置換コマンド(:s) |
| 選択範囲を目で確認しながら変更 | ビジュアルモード |
| 単語単位の書き換えを素早く | オペレータ+モーション |
最初は:sだけで何でも済ませていましたが、単語単位の書き換えが多い作業では明らかにオペレータ+モーションのほうが手数が少なくなりました。逆にファイル全体にまたがる置換でciwを繰り返すのは非効率で、結局は状況に応じて使い分けるのが一番速いという当たり前の結論に落ち着きました。
5つ目の方法:gn で「検索して書き換える」
もう1つ、gn という範囲指定があります。直前に検索した語にマッチする範囲を選ぶモーションで、cgn と打つと「次の該当箇所を書き換える」になります。
手元のVim 9.1.1752で /bar と検索してから cgn で打ち直すと、その語だけが置き換わりました。ここまでは ciw と変わりませんが、続けて . を押すと「次の該当箇所へ飛んで、同じ書き換えをする」まで一度に実行されます。
/bar<Enter> " 書き換えたい語を検索する
cgnBAR<Esc> " 1か所目を書き換える
. " 次の該当箇所へ飛んで同じ書き換え
n. " 1つ飛ばしたいときは n で送る
置き換えたい箇所とそのままにしたい箇所が混ざっているとき、これが最も手数が少なくなります。飛ばしたい箇所では n を押すだけで済むためです。
c フラグで確認しながら置換する
:s に c を付けると、1か所ごとに置換するかを聞いてきます。ここで押せるキーを知らないと、聞かれた時点で止まってしまいます。
y " 置換する
n " 置換せず次へ
a " 残り全部を置換する
q " ここで終了する
l " ここだけ置換して終了する
途中まで y と n で判断して、あとは同じでよいと分かった時点で a を押す、という使い方ができます。q で抜けてもそこまでの置換は残るので、やり直したければ u を1回押します。
取り消しの単位で選ぶ
どの方法を選ぶかは、失敗したときにどこまで戻したいかでも変わります。:s はコマンド1回ぶんがまとめて1つの変更になるので、u を1回押せば全部戻ります。
いっぽう cgn と . の組み合わせは1か所ずつが別々の変更なので、u を押した回数だけ戻ります。直前の1か所だけ取り消したいならこちら、全部やり直したいなら :s のほうが扱いやすい、という違いになります。
まとめ
行内の置換方法は1つに絞る必要はありません。文字数が同じならR、範囲が広いなら:s、単語単位ならオペレータ+モーション、と場面で切り替えられるようになると編集速度が安定します。行をまたいだ一括置換に広げたくなったら:substituteの活用集のほうが向いています。
ここで扱ったキーは、ブラウザ上で動くVim道場のまとめて置換するでそのまま試せます。インストールもログインも要りません。