JavaScript の正規表現マッチング

JavaScript正規表現 (RegExp オブジェクト) を使ってマッチングする方法。 しょっちゅう忘れてしまううえに ECMAScript 仕様に適合した方法があまり web 上に書かれていないようなので軽くメモしておきます。

RegExp.prototype.exec( string ) メソッド

正規表現のマッチングを試して、マッチした文字列全体とキャプチャリングした文字列を取得するためのメソッドが RegExp.prototype.exec( string ) メソッドです。

このメソッドは、マッチングが成功した場合は Array オブジェクトを返します。 その Array オブジェクトの第 0 要素はマッチした部分文字列全体です。 正規表現にキャプチャリングが含まれていた場合は、Array オブジェクトの第 1 要素以降に、順番にキャプチャリングされた文字列が格納されます。 さらに、この Array オブジェクトには index プロパティと input プロパティが定義され、それぞれの値は、正規表現が文字列にマッチした開始位置とマッチングの対象になった文字列全体です。

また、RegExp オブジェクトの global フラグが true であるならば、マッチした部分の最後の文字の次の文字の位置が、RegExp オブジェクトの lastIndex プロパティに保持されます。 同じ RegExp オブジェクトを使って再び exec メソッドを実行すると、そのときのマッチングは lastIndex プロパティの値から再開されます。 よって、while ループでマッチしなくなるまで繰り返す、ということが可能です。

なお、マッチしなかった場合には exec メソッドは null を返します。

// global フラグを true にした RegExp オブジェクト
var re = /<(\d+),(\d+)>/g;
var m;
// マッチする部分がある限り繰り返す
while( m = ( re.exec( "ab<32,43>cddd<faa>da<342,2>bcaaeabc" ) ) ) {
    // マッチした部分の開始位置
    print( m.index );
    // マッチした部分文字列全体 (Ruby などでは $& で参照できる)
    print( m.shift() ); // (第 0 要素だけを取り出している)
    // キャプチャされた部分 (Ruby などでは $1, $2, ... で参照できる)
    print( m.join( ", " ) ); // (元々の第 0 要素は既に取り出したので, 残りはキャプチャされた部分のみ)
}

JavaScript でも、バージョンによっては RegExp['$&'] としてマッチした部分文字列全体を参照したり RegExp.$1, RegExp.$2, ... としてキャプチャされた部分を参照できたりしましたが、非推奨となっており、使わないようにした方がいいでしょう。 (ちなみに RegExp.$& は基本的に構文エラーになってしまうので、RegExp['$&'] と書く必要がある。)

参考文献