まくまくVimノート
文字の置換方法いろいろ (:substitute)
2007-01-08
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  "15行目までを置換対象にする
:5,$ s/old/new/g  "5行目~最終行までを置換対象にする

Shift-V で行選択した状態から、:s/old/new/g と続けて実行することもできます(こちらの方法がオススメ)。 行選択した状態で : をタイプすると、コマンドの入力欄には下記のように表示されますが、これは行選した択範囲を操作対象としていることを示しています。 そのまま s/old/new/g と続けて入力すれば OK です。

:'<,'>

区切り文字にスラッシュ (‘/’) 以外を使用する

:s/old/new/g という置換コマンド自体がスラッシュを含んでいるため、置換対象の文字列にスラッシュが含まれる場合は、下記のようにバックスラッシュを使ったエスケープ処理が必要です(/ ではなく \/ と入力する)。

例: /home/aaa を /home/bbb に置換する

:% s/\/home\/aaa/\/home\/bbb/g

このようなエスケープ処理の煩雑さを防ぐために、substitute コマンドでは、セパレータ文字列としてスラッシュ以外のほとんどの種類の記号を使用できるようになっています。 下記の例は、セパレータ文字としてスラッシュの代わりにセミコロン (;) を使用しています。

例: /home/aaa を /home/bbb に置換する

:% s;/home/aaa;/home/bbb;g

正規表現を使ったパターン検索

<置換前パターン>の部分では正規表現を使用することができます。 ほとんどの特殊文字 (+など) は、バックスラッシュをつけてエスケープしないといけないことに注意してください。

特殊文字 意味
\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:] といった文字クラスも使用できますが、上記の特殊文字を覚えておけばほとんどのケースはカバーできるでしょう。

例: 単語の境界を意識して child を children に置換する

:% s/\<child\>/children/g

単語の境界を表すには、\<\> を使います。

例: ing で終わる単語を XXX に置換

:% s/\<[^ ]*ing\>/XXX/g

例: apple あるいは apples を banana に置換

:% s/apples\=/banana/g

例: カレント行から 5 行分の行頭に引用記号 (> ) を挿入する

:.,+4 s/^/> /

複数行の行頭に同じテキストを挿入したい場合は、上記のようなコマンドを使用するより、CTRL-V で行頭を矩形選択し、SHIFT-I でテキスト入力する、という方法の方が手軽です。

パターンに一致した文字列を置換後パターンの中で参照する

<置換前パターン>に実際に一致した文字列は、<置換後パターン>の中で & で参照することができます。

例: ファイル全体の google を google.com に置換する

:% s/google/&.com/g

上記の例では、&google と入力するのと同じ意味になります。

& が効果を発揮するのは、<置換前パターン>の中で正規表現を利用してパターン一致させた場合です。

例: 連続する数字を <> で囲む

:% s/\d\+/<&>/g

<置換前パターン>の中で、\(\) でパターンをグループ化しておくと、後から実際に一致した文字列を \1 で参照することができます。 複数のグループがある場合は、それぞれ \1\2\3 のように参照します。

例: 「」で囲まれた部分を『』で囲みなおす

:% s/「\(.\{-}\)」/『\1』/g

<置換前パターン>の中の \{-} という表現が分かりにくいかもしれませんが、これは直前の文字の 0 回以上の繰り返しで最短一致させる特殊表現です(* を使用すると最長一致になってしまう)。 この表現を使用することで、下記のように行内にパターン一致する部分が複数登場する場合にもうまく置換できます。

「これは」「サンプルの」「テキストだよ」
↓
『これは』『サンプルの』『テキストだよ』

大文字と小文字を変換する

例: すべての行の Help を大文字の HELP に置換する

:% s/help/\U&/g

\U は、その後ろに続くテキストをすべて大文字に変換します。 &<置換前パターン>に一致した実際のテキストを表すため、上記の場合は &help になります。 それがすべて大文字に変換されるため、結果的に HELP に置換されることになります。

例: カレント行をすべて大文字/小文字に置換する

:s/.*/\U&/g  "すべて大文字に置換
:s/.*/\u&/g  "すべて小文字に置換

SHIFT-V で行全体を選択して、U(あるいは u)とタイプしても同様のことを行えます。

パターンに一致する文字列を削除する

s コマンドによる置換を行うときに、<置換後パターン>を空っぽにしておけば、<置換前パターン>に一致する文字列を削除することができます。

例: 行頭のスペースとタブをすべて削除する

:% s/^\s\+//

例: 行末のスペースとタブをすべて削除する

:% s/\s\+$//

Vim では、正規表現の +\+ とエスケープしないといけないことに注意してください。

1 単語ずつ確認しながら置換する

c フラグによる置換実行確認

置換時に<フラグ>として c (confirm フラグ)を指定すると、置換対象となる文字列に関して、1 つずつ置換するかどうかを確認しながら置換していくことができます。 置換対象となる文字列が順番にハイライトされていくので、置換するなら y、置換しないなら n を入力していきます。

:% s/old/new/gc

検索しながら繰り返しコマンドで置換する方法

ちょっとマニアックですが、こんな手順で置換を繰り返していくこともできます。

  1. /<単語> で目的の単語を検索。
  2. cw で単語を置き換え、ESC で insert モードを抜ける。
  3. n で次の単語に移り、置換したい場合は . で置換。あとは 3 を繰り返す。

例: old という単語を検索しながら new に置き換えていく

/old
cwnew [Esc]
nnnn
.
nnn
.

まず old というテキストを検索し、cw コマンドでその単語を new に置換します。 あとは、n で次の単語を検索して置換したい位置で . によって置換コマンドを繰り返します。

置換パターンの中で改行を扱う

置換パターンの中で改行文字を入力するには、CTRL-VEnter(あるいは CTRL-QEnter)とタイプする必要があります。 コマンド入力欄には、^M と表示されて見えます。

例: aaa を bbb[改行]ccc に置換する

:% s/aaa/bbb^ccc/g

例: セミコロンの後ろに改行を挿入する

:% s/;/;^M/g
2007-01-08