思いこみ禁物 - Note @ Temporary-Depotで触れられていた、Perl・PHP・JavaScriptそれぞれにおける正規表現マッチの動作の違いが気になったので、自分でも確認してみました。
PHPでPerlと同じ動作にならなかったのは、例えば $v = 'http://localhost/' だった時に、"/^$v/"
で展開された正規表現パターンが /^http://localhost// となってしまうからだと思います。正規表現を囲うための文字(デリミタ)が、パターンの中にもそのまま現れているので、正規表現のパターンとして正しく読み取れなくなっているようです。
※ 自分が確認に使った環境(PHP 4.3.6)では、"Warning: Unknown modifier '/' in ..." というメッセージが出ていました。
PHPのマニュアルによると、スラッシュ(/)以外の記号や括弧類もデリミタとして使用できるそうなので、例えば以下のように変更することで、Perlと同じ結果が得られるかと思います。
if (preg_match("{^$v}", $referer)) echo("match! : " . $v . "<br />");
正規表現のデリミタに括弧を使うのは、「デリミタと同じ文字をパターンの中で使う場合はエスケープしなければ」という気づかいが要らないので、便利だと思います。個人的にも、Perlで正規表現マッチするときには /pattern/
よりも m{pattern}
という書き方をよく使います。
JavaScriptでPerlと同じ結果にならないのは、文字列のエスケープの違いによるもののようです。PerlやPHPでは\
を含む文字列をダブルクォート(")で囲ったときとシングルクォート(')で囲ったときとでは扱いが異なりますが、JavaScriptではどちらで囲っても、\
を常にエスケープ文字として扱うようです。
手っ取り早い確認方法: 以下のコードをブラウザのURL欄にコピー&ペーストしてEnterを押すと、true とalert表示されます。
javascript:alert('\/' === '/');
なので、配列変数check_urls
を以下のように設定しておけば、Perlと同様の結果を得られるかと思います。
var check_urls = [
'http://localhost/',
'http:\\/\\/localhost\\/',
'http://local\\w*?/'
];
追記: check_urls
の要素を予め正規表現リテラルにする手もありかも。
var check_urls = [ /^http:\/\/localhost\//, /^http:\/\/local\w*?\// ];
(…中略…)if(referer.match(check_urls[i])) document.write("match! : " + check_urls[i] + "<br />");