Vim の s
(substitute
) コマンドを使用すると、ファイル内の任意の範囲のテキストをまとめて置換することができます。
substitute コマンドの基本
substitute
コマンドは、ノーマルモード中に下記のように入力して実行します。
:<行範囲> s/<置換前パターン>/<置換後パターン>/<フラグ>
指定した <行範囲>
のテキストの中で、<置換前パターン>
に一致する文字列を <置換後パターン>
に置換します。
substitute
コマンドは通常、上記のように省略系の s
を使って実行します。
デフォルトでは、行内で最初に見つかった文字列だけを置換しますが、<フラグ>
部分に g
(global フラグ)を指定することで、行内のすべての文字列を置換することができます。
:s/old/new/ "カレント行の文字列を置換(1 つだけ置換)
:s/old/new/g "カレント行の文字列を置換(すべて置換)
上記のように <行範囲>
の指定を省略した場合は、カレント行のみが置換対象になりますが、そのような使い方はまれでしょう。
ファイル内の全ての行を置換対象にしたい場合は、<行範囲>
として %
を指定します(1,$
としても同様)。
下記の例では、%
の後ろにスペースを入れていますが、このスペースは省略することができます。
:% s/old/new/g "ファイル全体の文字列を置換
置換対象とする行範囲を指定したい時は、下記のように明示的に 開始行,終了行
を指定することもできますし、
:1,5 s/old/new/g "1~5行目までを置換対象にする
:5,$ s/old/new/g "5行目~最終行までを置換対象にする
Shift-V
で行選択した状態から、:s/old/new/g
と続けて実行することもできます(こちらの方法がオススメ)。
行選択した状態で :
をタイプすると、コマンドの入力欄には下記のように表示されますが、これは行選した択範囲を操作対象としていることを示しています。
そのまま s/old/new/g
と続けて入力すれば OK です。
:'<,'>
区切り文字にスラッシュ (/) 以外を使用する
:s/old/new/g
という置換コマンド自体がスラッシュを含んでいるため、置換対象の文字列にスラッシュが含まれる場合は、下記のようにバックスラッシュを使ったエスケープ処理が必要です(/
ではなく \/
と入力する)。
このようなエスケープ処理の煩雑さを防ぐために、substitute
コマンドでは、セパレータ文字列としてスラッシュ以外のほとんどの種類の記号を使用できるようになっています。
下記の例は、セパレータ文字としてスラッシュの代わりにセミコロン (;
) を使用しています。
正規表現を使ったパターン検索
<置換前パターン>
の部分では正規表現を使用することができます。
ほとんどの特殊文字(+
など)は、バックスラッシュをつけてエスケープしないといけないことに注意してください。
特殊文字 | 意味 |
---|---|
\a | アルファベット文字に一致([A-Za-z] と同様) |
\A | 非アルファベット文字に一致([^A-Za-z] と同様) |
\d | 数字に一致([0-9] と同様) |
\D | 非数字に一致([^0-9] と同様) |
\w | 英数字に一致([0-9A-Za-z] と同様) |
\W | 非英数字に一致([^0-9A-Za-z] と同様) |
\o | 8進数に一致([0-7] と同様) |
\O | 非8進数に一致([^0-7] と同様) |
\x | 16進数に一致([0-9A-Fa-f] と同様) |
\X | 非16進数に一致([^0-9A-Fa-f] と同様) |
\s | スペースあるいはタブに一致 |
\S | スペースでもタブでもない文字に一致 |
\t | タブ文字に一致 |
. | 任意の 1 文字に一致 |
\+ | 前の文字の 1 回以上の繰り返し(できるだけ多くの回数に一致) |
\{-1,} | 前の文字の 1 回以上の繰り返し(最も少ない回数に一致) |
* | 前の文字の 0 回以上の繰り返し(できるだけ多くの回数に一致) |
\{-} | 前の文字の 0 回以上の繰り返し(最も少ない回数に一致) |
\= | 前の文字の 0 回、あるいは 1 回に一致(一般的な正規表現の ? に相当) |
\< | 単語の始まりに一致 |
\> | 単語の終わりに一致 |
[ | 文字グループの開始 |
] | 文字グループの終了 |
^ | 行頭に一致(文字グループの先頭で使用すると「それ以外の文字」の意味になる) |
$ | 行末に一致 |
パターン|パターン | どちらかのパターンに一致 |
\(パターン\) | 一致部分を後から参照するためにマークする |
ほとんどの文字はエスケープしなければいけないので、エスケープしなくてもよい特殊文字を覚えておくのがよいでしょう(.
、*
、[
、]
、^
、$
)。
逆にこれらを、その文字そのものとして扱う場合はエスケープが必要です(例: .
という文字に一致させたいなら \.
と入力する)。
[:alnum:]
や [:alpha:]
、[:digit:]
といった文字クラスも使用できますが、上記の特殊文字を覚えておけばほとんどのケースはカバーできます。
実際には、複数行の行頭に同じテキストを挿入したい場合は、上記のようなコマンドを使用するより、CTRL-V
で行頭を矩形選択して SHIFT-I
でテキスト入力する、という方法の方が手軽です。
パターンに一致した文字列を置換後パターンの中で参照する
<置換前パターン>
に実際に一致した文字列は、<置換後パターン>
の中で &
で参照することができます。
上記のように記述すると、&
の部分に google
と記述したのと同じ振る舞いをします。
上記の使い方はあまり意味がないかもしれませんが、次のように正規表現を使用してパターンマッチングさせた場合に効果を発揮します(実際に一致した文字列は &
で参照するしかありません)。
<置換前パターン>
の中で、\(
と \)
でパターンをグループ化しておくと、後から実際に一致した文字列を \1
で参照することができます。
複数のグループがある場合は、それぞれ \1
、\2
、\3
のように参照します。
<置換前パターン>
の中の \{-}
という表現が分かりにくいかもしれませんが、これは直前の文字の 0 回以上の繰り返しで最短一致させる特殊表現です(*
を使用すると最長一致になってしまいます)。
この表現を使用することで、下記のように行内にパターン一致する部分が複数登場する場合にもうまく置換できます。
大文字と小文字を変換する
すべての行の Help を大文字の HELP に置換する
:% s/help/\U&/g
\U
は、その後ろに続くテキストをすべて大文字に変換します。
&
は <置換前パターン>
に一致した実際のテキストを表すため、上記の場合は &
は help
になります。
それがすべて大文字に変換されるため、結果的に HELP
に置換されることになります。
カレント行をすべて大文字/小文字に置換する
:s/.*/\U&/g "すべて大文字に置換
:s/.*/\u&/g "すべて小文字に置換
SHIFT-V
で行全体を選択して、U
(あるいは u
)とタイプしても同様のことを行えます。
パターンに一致する文字列を削除する
s
コマンドによる置換を行うときに、<置換後パターン>
を空っぽにしておけば、<置換前パターン>
に一致する文字列を削除することができます。
Vim では、正規表現の +
は \+
とエスケープしないといけないことに注意してください。
- 参考: 正規表現にマッチする行を削除する
1 単語ずつ確認しながら置換する
c フラグを使う方法
置換時に <フラグ>
として c
(confirm フラグ)を指定すると、置換対象となる文字列に関して、1 つずつ置換するかどうかを確認しながら置換していくことができます。
置換対象となる文字列が順番にハイライトされていくので、置換するなら y
、置換しないなら n
を入力していきます。
:% s/old/new/gc
検索しながら繰り返しコマンドで置換する方法
ちょっとマニアックですが、こんな手順で置換を繰り返していくこともできます。
/<単語>
で目的の単語を検索。cw
で単語を置き換え、ESC
で insert モードを抜ける。n
で次の単語に移り、置換したい場合は.
で置換する、という操作を繰り返す。
この操作例では、まず old
というテキストを検索し、cw
コマンドでその単語を new
に置換しています。
あとは、n
で次の置換対象までジャンプし、.
で置換コマンドを再実行しています。
置換パターンの中で改行を扱う
置換パターンの中で改行文字を入力するには、CTRL-V
→ Enter
(あるいは CTRL-Q
→ Enter
)とタイプする必要があります。
コマンド入力欄には、^M
と表示されて見えます。