Vimの正規表現 “\v”, “\zs”, “\ze”

Vimの小ネタ。

Vimで正規表現を使うとき、Perlなんかと比べると制御文字を書くときにバックスラッシュを多用するため見にくく感じていた。たとえば、

「abc」と「def」に挟まれた文字列

を表す正規表現というと、Perlなら

/(?<=abc).+(?=def)/

で済むところ、Vimだと

\(abc\)\@<=.\+\(def\)\@=

となるのでめんどくせえ〜とか思ってたわけだ。

とんでもない間違いでした。

便利な制御文字があったんだね。こんなときに使うのが「\v」。これを使うと英数字以外が全て制御文字と見なされるので、表記が格段にシンプルになる。同じ例だと、

\v(abc)@<=.+(def)@=

こちらが圧倒的に見易い。ちゃんとヘルプ読まないとダメだねorz

そしてさらに便利なのが「\zs」と「\ze」。これは正規表現の「始まり」と「終わり」を表す。同じ例を表すと、

abc\zs.\+\zedef

ちょっと見にくいかもしれないけど意味は同じだ。これを使えばPerlの正規表現では対応していない、「可変長の後読み」を実現できる。例えば、

<p>Hello!</p>
<script>alert( "Hello!" )</script>
<script type="javascript">alert( "Hello!" )</script>

このHTMLから<script>タグの中身だけを取ろうとして、

/(?<=<script.*>).+(?=<\/script>)/

とやってもうまく行かない。

$ perl -e '/(?<=<script.*>).+(?=<\/script>)/'
Variable length lookbehind not implemented in regex m/(?<=<script.*>).+(?=</script>)/ at -e line 1.

「可変長の後読みは未実装です」エラーになってしまう。しかしVimだと楽ちん。

<script.*>\zs.\+\ze<\/script>

100205-0002.png

これを知って検索・置換がずいぶん早くなった。

特定のメール(Outlook)を自動的に削除するスクリプト

社内で「特定人物向けのメールを全員に送信しちゃった! 何とかして!」と言われたときに作ったスクリプト。グループポリシーを使ってPCにログオンしたときに起動するように設定することを想定している。Outlookを自動的に起動して受信メールをチェックし、条件に合うもの(今回は特定の語句を題名に含むもの)を削除する。

Continue reading