:substituteコマンド活用集 全置換・行頭行末への挿入・確認付き置換
:s///の基本形は知っていても、行頭に文字列を追加したいときや、置換前に1件ずつ確認したいときにどう書けばいいか毎回思い出せません。よく使うパターンをまとめて手元に置いておきます。
目次(14項目)
| パターン | これだけ覚える |
|---|---|
:%s/foo/bar/g | ファイル全体を一括置換 |
:%s/^/# /g | 全行の行頭に文字列を追加 |
:%s/$/;/g | 全行の行末に文字列を追加 |
:%s/foo/bar/gc | 1件ずつ確認しながら置換 |
基本形
:[range]s[ubstitute]/{pattern}/{string}/[flags]
rangeを省略すると現在行だけが対象になります。ファイル全体を対象にしたいときは%を先頭に付けます。
1. ファイル全体を一括置換する
:%s/foo/bar/g
%で全行、gフラグで1行内の複数マッチもすべて対象にします。gを付けないと各行の最初のマッチだけが置換される点に注意してください。
2. 全行の行頭に文字列を追加する
foo = 1 bar = 2 baz = 3
:%s/^/# /g# foo = 1 # bar = 2 # baz = 3
マッチパターンを行頭を表す^にすると、何も消さずに指定した文字列だけを挿入できます。コメントアウトしたい行をまとめて選んでこのパターンを使えば、一括コメントアウトになります。
3. 全行の行末に文字列を追加する
:%s/$/;/g
行末を表す$を使えば、同じ要領で行末に文字列を追加できます。CSVの各行にカンマを補いたい、SQLの各行にセミコロンを付けたい、といった場面で使います。
4. 1件ずつ確認しながら置換する
:%s/foo/bar/gc
cフラグを付けると、マッチするたびに置換するかどうかを聞かれます。一括置換に自信が持てないときは、まずc付きで試すと事故を防げます。
| キー | 動作 |
|---|---|
| y | この箇所を置換する |
| n | この箇所をスキップする |
| a | 残り全部を置換する |
| q | 確認を終了する |
:%s/config/cfg/gc を実行したところ。1か所ごとに y n a q l で答える置換後の文字列に検索結果を埋め込む
:%s/\(\d\+\)/[\1]/g " 数字を角括弧で囲む
\(...\)でグループ化した部分は、置換後の文字列側で\1のように参照できます。マッチした内容の一部を活かしたまま前後に文字を足したいときは、パターン全体を消して打ち直すのではなく、グループ参照を使うと効率的です。
範囲を限定したいとき
:5,10s/foo/bar/g " 5〜10行目だけを対象にする
ビジュアルモードで範囲を選択してから:を押すと:'<,'>s/が自動的に入力され、選択した範囲だけを対象にできます。
cで確認しながら置換。基本形さえ覚えれば、あとはパターンとフラグの組み合わせでほとんどのケースに対応できます。
複数行にまたがるSQLの末尾にカンマを付け忘れて何度もやり直した経験から、:%s/$/,/gで行末挿入をまとめて済ませる癖がつきました。範囲を間違えて余計な行まで置換してしまった苦い経験もあり、それ以来ファイル全体に影響する置換は必ずcフラグを付けて確認するようにしています。
大文字小文字を区別する・しないを切り替える
:%s/foo/bar/gi " 大文字小文字を区別しない
:%s/foo/bar/gI " 大文字小文字を区別する
'ignorecase'を設定していない環境ではデフォルトで大文字小文字が区別されますが、iフラグを付ければ一時的に区別なしで検索できます。逆に'ignorecase'を常時オンにしている環境では、特定の置換だけ厳密に区別したい場合にIフラグが使えます。
単語の境界を厳密に指定したいときは、パターン側に単語境界の指定を加えると便利です。
:%s/\<foo\>/bar/g " "foo"という単語だけにマッチ(fooobarのような部分一致を除外)
\</\>はそれぞれ単語の先頭・末尾の境界を表します。foobarのような文字列の一部にfooが含まれていても誤ってマッチしないようにしたいときに使います。
選択範囲だけを対象にする
:'<,'>s/foo/bar/g
ビジュアルモードで対象範囲を選択してからコマンドラインに入ると:'<,'>が自動的に補われます。ファイル全体ではなく一部の行だけに置換をかけたいときは、行番号を数えるより範囲選択してから:を押したほうが確実です。
区切り文字は / でなくてよい
パスを扱うときに / を区切りにすると、パターンの中の / をすべて打ち消すことになって読めなくなります。区切り文字は自由に選べます。
:%s#/usr/local#/opt#g " # を区切りにする
:%s,../lib,./lib,g " , を区切りにする
使えるのは英数字とバックスラッシュ以外の記号です。置換前後に何が入るかを見て、その中に出てこない記号を選ぶのが要点になります。
行をまたいで置換する
パターン側の \n は改行に一致し、置換後の側では \r が改行を意味します。この2つが逆なのが引っかかりやすいところです。
:%s/foo\nbar/foobar/ " 2行を1行にまとめる
:%s/,/\r/g " カンマで行を分ける
:%s/;\n/;/ " セミコロンの後ろの改行を消す
置換後に \n と書くとヌル文字が入ってしまい、意図しない結果になります。改行を入れたいときは必ず \r です。行をつなぐだけなら J のほうが手軽なので、条件付きでつなぎたいときにこの書き方を使います。
同じ置換をもう一度かける
置換コマンドは . では繰り返せません。代わりに & を押すと、直前の置換を今いる行にもう一度かけられます。
& " 直前の置換を今の行に(フラグは引き継がない)
:&& " フラグ込みで今の行に
:%&& " フラグ込みでファイル全体に
まず1行で試し、思ったとおりなら :%&& で全体に広げる、という進め方なら、失敗しても戻す範囲が小さくて済みます。範囲の広い置換ほど、この段取りが効いてきます。
まとめ
:substituteは^/$による位置指定とcフラグによる確認だけ覚えておけば、日常的な置換作業の大半をカバーできます。最短マッチが必要な複雑なパターンは別記事を参照してください。行内だけで済む書き換えなら行内の置換4パターンのほうが手数が少なく済みます。
ここで扱ったキーは、ブラウザ上で動くVim道場のまとめて置換するでそのまま試せます。インストールもログインも要りません。