2007-09-09

文字列リテラルにマッチする正規表現

JavaScriptの正規表現で、文字列リテラル(引用符「"」で囲まれた文字列、例えば、"abc")に一致するパターンを考えてみた。

/".*?"/で済めば良いのだが、これでは文字列中にエスケープされた引用符(\")が存在する場合に対処できない。文字列を閉じる引用符の直前にバックスラッシュ(\)が無ければ良いと考えて/".*?[^\\]"/としてみるも、今度はバックスラッシュがエスケープされていた場合(例えば、"abc\\")に対処できない。

試行錯誤の結果、/"(.*?[^\\])??(\\\\)*"/という結論に至った。前半が「(...)??」という形になっているのは「""」や「"\\"」にもマッチさせるため。

追記(2007-10-19)

コメントでもっと良い表現を教えていただきました。教えていただいたのはJavaの正規表現で、JavaScriptの正規表現リテラルに直すと/"([^\\"]|\\.)*?"/となります。

追記(2007-11-18)

上記の正規表現ですが、「[^\\"]」の部分でエスケープされていない「"」を含まないようになっているので、「(...)*?」のように「*?」を使う必要はなく、「*」で十分です。つまり、文字列リテラルに一致する正規表現は/"([^\\"]|\\.)*"/となります。

コメント (2)

みゆ さんのコメント...
はじめまして。みゆといいます。
私も文字列リテラルにマッチする正規表現を考えていて,たまたまここに行き着きました。

記載されているやり方ではうまくいかなかったので,わたしもいろいろ試してみたところ,ダブルコーテーションも含めて,

\"(?>[^\\\\\"]|\\\\.)*?\"

とすることでうまくいきました。

わたしはJava(J2SE 6.0)で確認しました(そのため2重にエスケープしてあります)が,Perlとも大差ないと思います。
Ku_zu_ さんのコメント...
ゆみさん、コメントありがとうございます。
「\\.」でエスケープシーケンスを表現すれば良いことを考えていなかったので、勉強になりました。