Vimの検索機能をもうちょっとだけ

Vimの置換機能で指定できる範囲指定方法、行指定方法、パターン、繰り返しパターン、置換後文字列で指定できる特殊な文字列、フラグに関しては稿末に付録としてまとめておくので参考にしていただきたい。それらの指定方法を全て覚えている人は稀だと思う。よく使う便利なものについては覚えていたほうがよいが、それ以外は必要になったときに参照して利用すればよいだろう。

Vimの置換機能についての解説は、今回でとりあえず終えるつもりだ。最後に取り上げる機能はあまり使わないかもしれないのだが、知っておくと今後もし必要になったときや、Vim以外のコマンドで似たようなことを処理しなければいけないときに役立つ可能性がある。こういったことができるんだ、ということを知っておいてもらえればよいと思う。

後方一致/前方一致+行移動からの置換

Vimでは置換を適用する範囲を指定してから置換処理を記述するわけだが、そうした範囲の指定において次のような書き方ができる。

行指定 内容
/パターン/ パターンに一致する行(後方一致)
?パターン? パターンに一致する行(前方一致)
+数字 一致した行からさらに指定行数分後方へ移動した行
-数字 一致した行からさらに指定行数分前方へ移動した行

どのように上記の範囲指定を行うのかだが、「/」や「?」によるコマンドラインモードでの検索を行ってから、カーソルを上下に移動させ、移動先で置換を実行する、といったような使い方をイメージしてもらえればよい。

例えば、前回と同じくMarkdownの書き方を変換する方法をサンプルとして取り上げるとする。

置換処理のサンプルテキスト

上記テキストにおいて「## タイトル」の部分を下線を書くタイプのタイトルにスタイル変更するとしよう。前回はグルーピング、後方参照、置換後文字列に改行を含める、といったスキルを使って変換を行った。今回は次のような置換方法で処理を行う。

:/^##/+1s/^/ーーーーーーーーーーーーーーーーーー/

この入力は次のような命令になっている。

入力 内容
: コマンドラインモードへ移行
/^##/ 先頭が「##」で始まっている行へ移動
+1 1つ下の行に移動
s/^/ーーーーーーーーーーーーーーーーーー/ 行頭を「ーーーーーーーーーーーーーーーーーー」へ置換

今回の指定方法としてはコマンドラインモードに入ってから範囲を指定する方法として「/^##/+1」という書き方をしている点にある。「/^##/」で行の先頭が「##」で始まっている行へ移動し、その次に記載されている「+1」によって移動した行の次の行へ移動している。処理を実行すると次のようになる。

後方一致および行移動からの置換処理

置換実行後

「/キーワード/」で範囲を指定した場合、処理は1回だけ実施される。「/キーワード/」は後方一致なので、逆に上の方に対して検索を行っていく場合には以下のように「?キーワード?」という指定で対象への一致を行う。

:?^##?+1s/^/ーーーーーーーーーーーーーーーーーー/

実行すると次のようになる。

前方一致を試すためにカーソルをここへ移動させてから

前方一致および行移動からの置換処理

置換実行後

前回紹介したように、検索対象や検索後文字列に改行を含める形で置換を実施すれば前述したような一致や行移動からの置換を行う必要はないが、こういったこともできると知っておくとよいと思う。

一致を全てに対して実行する「:g」

上記の方法だと、一致対象1つだけに置換処理が行われるが、Vimでは次のように「:global」または「:g」という指定と組み合わせることで、一致する全てに対して処理を行わせることができる。

:g/^##/+1s/^/ーーーーーーーーーーーーーーーーーー/

実行結果は以下の通りだ。

一致対象全てに対して置換を行わせる命令

置換実行後

今回の用途に限って言えば、一致と行移動からの処理よりも、改行を含めた置換処理を書いたほうが簡単だし、便利だ。しかし、一致からの行移動といった使い方もできるということは覚えておいて損はないと思う。「こういうデータの次の行に〇〇と書く」とか「こういうデータの前の行に××と書く」といったこともあるので、この書き方を知っておくとデータ処理の要求から置換命令への書き出しがスムーズにできるようになる。

利用する頻度はユーザーによるとは思うが、余裕があるならぜひ覚えておいていただきたい。

付録: 置換関連機能テーブル

パターン 内容
^ 行頭(パターンの先頭でのみ指定可能)
$ 行末(パターンの末尾でのみ指定可能)
. 任意の1文字(行末には使用できない)
\%^ ファイルの先頭
\%$ ファイルの終了
\%V Visual領域の中
\%# カーソルの位置
\%’m マークm位置
\%数字l 指定行
\%数字c 指定列
\%数字v 指定仮想列
\_^ 行頭(パターンのどこでも指定可能)
\_$ 行末(パターンのどこでも指定可能)
\_. 任意の1文字(行末としても指定可能)
\< 単語の先頭
\> 単語の末尾
\zs 一致の開始を指定
\ze 一致の終了を指定
\^ ^
\$ $
. .
\e <ESC>
\t <TAB>
\r <CR>
\b <BS>
\n 行末
[] カッコ内に指定した文字のどれかに一致
\(\) グループ化
\1 1つ目の\(\)の中身に一致
\2 2つ目の\(\)の中身に一致
\3 3つ目の\(\)の中身に一致
\4 4つ目の\(\)の中身に一致
\5 5つ目の\(\)の中身に一致
\6 6つ目の\(\)の中身に一致
\7 7つ目の\(\)の中身に一致
\8 8つ目の\(\)の中身に一致
\9 9つ目の\(\)の中身に一致
\c 大文字小文字を区別せずに一致
\C 大文字小文字を区別して一致
\%d 10進数に一致
\%x 16進数に一致
\%o 8進数に一致
\%u マルチバイト文字に一致
\%U ラージマルチバイト文字に一致
\%C 合成文字に一致
\i 識別子文字
\I 識別子文字(数字は含まない)
\k キーワード文字
\K キーワード文字(数字は含まない)
\f ファイル名文字
\F ファイル名文字(数字は含まない)
\p 印刷可能文字
\P 印刷可能文字(数字は含まない)
\s 空白とタブ
\S 空白とタブ以外の文字
\d 数字([0-9])
\D 数字以外([^0-9])
\x 16進数([0-9A-Fa-f])
\X 16進数以外([^0-9A-Fa-f])
\o 8進数([0-7])
\O 8進数以外([^0-7])
\w 単語文字([0-9A-Za-z_])
\W 単語文字以外([^0-9A-Za-z_])
\h 単語の先頭文字([A-Za-z_])
\H 単語の先頭文字以外([^A-Za-z_])
\a アルファベット([A-Za-z])
\A アルファベット以外([^A-Za-z])
\l 小文字アルファベット([a-z])
\L 小文字アルファベット以外([^a-z])
\u 大文字アルファベット([A-Z])
\U 大文字アルファベット以外([^A-Z])
\_d 数字(行末を含む)
\_D 数字以外(行末を含む)
\_x 16進数(行末を含む)
\_X 16進数以外(行末を含む)
\_o 8進数(行末を含む)
\_O 8進数以外(行末を含む)
\_w 単語文字(行末を含む)
\_W 単語文字以外(行末を含む)
\_h 単語の先頭文字(行末を含む)
\_H 単語の先頭文字以外(行末を含む)
\_a アルファベット(行末を含む)
\_A アルファベット以外(行末を含む)
\_l 小文字アルファベット(行末を含む)
\_L 小文字アルファベット以外(行末を含む)
\_u 大文字アルファベット(行末を含む)
\_U 大文字アルファベット以外(行末を含む)
繰り返しパターン 内容
* 直前指定の0回以上の繰り返し(より長い方に一致)
\+ 直前指定の1回以上の繰り返し(より長い方に一致)
\= 直前指定の0回または1回の繰り返し(より長い方に一致)
\? 直前指定の0回または1回の繰り返し(より長い方に一致)
\{n,m} 直前指定のn回以上m回以下の繰り返し(より長い方に一致)
\{n} 直前指定のn回の繰り返し
\{n,} 直前指定のn回以上の繰り返し(より長い方に一致)
\{,m} 直前指定のm回以下の繰り返し(より長い方に一致)
\{} 直前指定の0回以下の繰り返し(より長い方に一致)
\{-n,m} 直前指定のn回以上m回以下の繰り返し(より短い方に一致)
\{-n} 直前指定のn回の繰り返し
\{-n,} 直前指定のn回以上の繰り返し(より短い方に一致)
\{-,m} 直前指定のm回以下の繰り返し(より短い方に一致)
\{-} 直前指定の0回以下の繰り返し(より短い方に一致)
置換後文字列で使える特別な文字列 内容
& 一致したパターン全体に一致
\& &
~ 前の置換文字列に一致
\~ ~
\0 一致したパターン全体に一致
\1 1つ目の\(\)の中身に一致
\2 2つ目の\(\)の中身に一致
\3 3つ目の\(\)の中身に一致
\4 4つ目の\(\)の中身に一致
\5 5つ目の\(\)の中身に一致
\6 6つ目の\(\)の中身に一致
\7 7つ目の\(\)の中身に一致
\8 8つ目の\(\)の中身に一致
\9 9つ目の\(\)の中身に一致
<CR> 行を2つに分割。<CR>はCtrl-V Enterで入力する
\r 行を2つに分割。<CR>はCtrl-V Enterで入力する
\<CR> キャリッジリターン(Ctrl-M)を挿入。<CR>はCtrl-V Enterで入力する
\n <NL>を挿入。改行はしない
\b <BS>を挿入
\t <Tab>を挿入
\ \
範囲指定 内容
開始行,終了行 開始行から終了行までを範囲とする
カーソルのある行のみを範囲とする
% ファイル全体を範囲とする
行指定 内容
数字 行番号
. カーソルがある行
$ ファイル末尾行
% 1,$に同じ
‘< ビジュアル選択の開始行
‘> ビジュアル選択の終了行
/パターン/ パターンに一致する行(後方一致)
?パターン? パターンに一致する行(前方一致)
+数字 一致した行からさらに指定行数分後方へ移動した行
-数字 一致した行からさらに指定行数分前方へ移動した行
フラグ 内容
c 置換ごとに確認。y (置換を実施)、l (置換の実施と置換の終了)、n (置換をスキップ)、ESC (置換を終了)、a (すべての置換を実施)、q (置換を終了)、Ctrl-E (スクリーンアップ)、Ctrl-Y (スクリーンダウン)
g 行に含まれるすべての一致対象を置換。このフラグを指定しなかった場合、行に含まれる最初に一致した対象のみが置換される
i パターンの大文字と小文字を区別しない
I パターンの大文字と小文字を区別する
n 置換を実行せずに一致する対象数を報告