Emacs Lispを基礎から学ぶ (2): 正規表現

elisp正規表現はむずかしい

残念なことにelispには正規表現リテラルが存在しないため、関数やコマンドに正規表現を渡すためには文字列として渡す必要がある。

他の言語の正規表現と同様、elisp正規表現でもバックスラッシュを含むメタ文字("\w"とかグルーピング用の"\("とか)が多用されるワケだけど、文字列中ではこれらのメタ文字に含まれるバックスラッシュをエスケープ文字として処理しなければならない。

たとえば、正規表現"\(\w.\)"を文字列で表現するためには"\\(\\w*\\)"と書く必要があり、ただでさえ読みにくく書きにくい正規表現が大量のバックスラッシュにより暗号のようになってしまう。テキスト処理がメインの言語のはずなのに...

re-builderで対話的に正規表現を書く

ただ、るびきちさんの本にも書かれている通り正規表現を少しでもラクに書くためのworkaroundはいくつか用意されている。ひとつはemacs標準添付のre-builderというツールで正規表現を対話的に書く方法。
検索対象のテキストを含むバッファで M-x re-builder とコマンドを打つと、正規表現を入力するための小さいウィンドウが開かれる:
f:id:yhashy:20120714120628p:plain
ここで正規表現を入力すると、元のバッファでマッチするテキストがハイライトされるので、結果を確認しながら正規表現を編集できてラクチンですね、というお話。

RubyのRubularみたいなものかな。
Rubular: a Ruby regular expression editor and tester

正規表現を生成する関数・マクロを使う

もうひとつの方法は、正規表現自体を自分で書かずに関数で生成してしまおう、という方法。
関数regexp-optに文字列のリストを渡すと、その文字列すべてにマッチする最適化された正規表現を返してくれる。
また、rxマクロは独自のミニ言語で生成する正規表現を記述することができる(ただこの言語の書き方覚えるのが少しめんどくさそう)。

正規表現にマッチする関数

練習コード書いたのに忘れてた。

正規表現と文字列を渡して、マッチした部分のインデックスを返す関数はstring-match.
対して、正規表現マッチ時にグルーピング指定した文字列を取り出す関数はmatch-stringとなる(どっちがどっちかややこしい)。