正規表現ラボを作ってる最中、何度も「あれ、これPHPで動いたのになんでJSだと動かないんだ」を経験しました。正規表現って言語問わず同じもの、というイメージを持ってる人もいると思うんですが(自分も昔はそうでした)、実際には結構がっつり方言があります。
後読みで本番を壊した話
たとえば肯定先読み(?=...)とか否定先読み(?!...)あたりは大体どの言語でも使えるんですが、長さの決まってない後読みになると途端に言語・エンジンごとの対応がバラバラになります。JavaScriptは比較的最近になって後読みに対応した経緯があって、「古い環境だと動かない」みたいな地味な罠が実務でちょくちょく発生します。
自分も1回、これで本番エラーを出してしまい、深夜に平謝りしながら直した苦い記憶があります。
PHPのpreg_matchまわりはPCREというエンジンを使っていて、JavaScriptの正規表現エンジンとはデリミタの要否やUnicodeモードの指定方法なんかが微妙に違います。「微妙に」というのが厄介なところで、大体は動くんだけど、たまにコーナーケースだけ挙動が変わる。
| JavaScript | PHP(PCRE) | |
|---|---|---|
| デリミタ | 不要(/pattern/で表現) | 必須(/pattern/のように囲む) |
| Unicodeモード | uフラグ | u修飾子 |
| 可変長後読み | 比較的最近対応 | 早くから対応 |
この「大体動く」が一番怖いんですよね。全部動かないなら気づけるんですが。
バックエンドとフロントエンドの両方でバリデーションを書くような場面だと、この方言の違いを忘れてると「サーバー側は弾いたのにクライアント側は素通りした」みたいな不整合がふつうに起こります。正規表現ラボにJS・PCRE両方をその場で試せる機能を入れたのも、この「動いたから正しいとは限らない」を身をもって知ってほしかったからです。自分がやらかした分、余計に力が入りました。
