RegExpオブジェクトは、正規表現のためのオブジェクトです。
文字列をスラッシュで囲んで記述することで、正規表現のパターンを指定する正規表現リテラルとみなされます。たとえば、
var pattern = /[0-9]+/g;
とすると、patternはRegExpオブジェクトとして生成されます。
通常は正規表現リテラルでも代用できますが、正規表現のパターンを動的に生成する必要があるときには、コンストラクタにより明示的に生成します。
new RegExp( pattern [, flags ] );
このオブジェクトを生成するには、
var pattern = new RegExp( '[0-9]+', 'g' );
のようにします。このコードにより生成されるRegExpオブジェクトは、前述の正規表現リテラルと同一です。
new RegExp( 'a' ); // /a/ new RegExp( '' ); // /(?:)/ new RegExp( '[0-9]+', 'g' ); // /[0-9]+/g
コンストラクタのflags引数には、次のいずれかを指定できます。
文字 | 意味 |
---|---|
i |
大文字と小文字を区別しない |
g |
グローバル検索 (グローバルマッチ)
一致するもの、すべてを検索する。 |
m |
マルチラインモード
「^」は文字列と行の先頭、「$」は文字列と行の末尾に一致させる。 |
Perlなどのマッチモードにあるs
フラグ (シングルラインモード) はサポートされないため、複数行を処理できません。
プロパティ | 内容 |
---|---|
global | 「g」属性を持つかどうか |
ignoreCase | 「i」属性を持つかどうか |
multiline | 「m」属性を持つかどうか |
lastIndex | 最後にマッチした文字の位置 |
source | 正規表現オブジェクトのソーステキスト |
メソッド | 説明 |
---|---|
exec | 文字列のパラメータでマッチングを行う |
test | 文字列にパターンが含まれているか調べる |
compile | 正規表現をコンパイルする。これは基本的にRegExpコンストラクタと同じ [非推奨] |
通常のパターンマッチングでは行えないような複雑な処理をするには、exec()メソッドを使用します。とくにグローバルマッチで部分正規表現を取得するには、このメソッドでなければなりません。
regexObj.exec( str );exec - JavaScript | MDN
たとえば次のコードを実行した場合、
var text = 'Hello! world';
var pattern = /l+/g;
var match;
while( match = pattern.exec( text ) )
{
// @todo
}
exec()の結果は、
ループ回数 | match | match.index | match.input | pattern.lastIndex |
---|---|---|---|---|
1回目 | ["ll"] | 2 | "Hello! world" | 4 |
2回目 | ["l"] | 10 | "Hello! world" | 11 |
3回目 | null | --- | 0 |
のように返されます。このときパターンをグローバルマッチとせず/l+/
とすると、
ループ回数 | match | match.index | match.input | pattern.lastIndex |
---|---|---|---|---|
1回目 | ["ll"] | 2 | "Hello! world" | 0 |
2回目 | ["ll"] | 2 | "Hello! world" | 0 |
3回目 | ["ll"] | 2 | "Hello! world" | 0 |
4回目 | ︙ | ︙ | ︙ | ︙ |
のように、1回目と同じ結果が返され続けます。
lastIndexプロパティはマッチを開始する位置を表し、その値はマッチした場合のみ進みます。
マッチした | マッチしなかった | |
---|---|---|
lastIndexの位置が文字列の末尾より前 | マッチした文字列の数だけ加算 | 変化なし |
lastIndexの位置が文字列の末尾 | マッチした文字列の数だけ加算 | 0にリセット |
lastIndexの位置が文字列の末尾より後 | (決してマッチしない) | 0にリセット |
lastIndexの値はString.match()やString.search()によっても変化しますが、これらのメソッドへは影響しません。
var text = '123'; var pattern = /[0-9]/g; pattern.lastIndex = 1; console.log( text.match( pattern ) ); // [ "1", "2", "3" ] console.log( pattern.lastIndex ); // 0 pattern.lastIndex = 1; console.log( text.search( pattern ) ); // 0 console.log( pattern.lastIndex ); // 1
lastIndexプロパティに値を設定することで、マッチさせる位置を制御できます。RegExp.lastIndex - JavaScript | MDN
var text = '12345'; var pattern = /[0-9]/g; alert( pattern.exec( text ) ); // 1 alert( pattern.exec( text ) ); // 2 alert( pattern.exec( text ) ); // 3 pattern.lastIndex = 0; alert( pattern.exec( text ) ); // 1 alert( pattern.exec( text ) ); // 2 pattern.lastIndex = 10; alert( pattern.exec( text ) ); // null
regexObj.test( str );RegExp.test - JavaScript | MDN
正規表現がstrにマッチしたならば、trueが返されます。
new RegExp( '[0-9]' ).test( 'abc' ); // false new RegExp( '[0-9]' ).test( '123' ); // true
test()はexec()同様、グローバルマッチで複数呼び出すと、マッチした場合にはlastIndexプロパティが進みます。
var text = '123'; var pattern = /[0-9]/g; console.log( pattern.test( text ) ); // true console.log( pattern.test( text ) ); // true console.log( pattern.test( text ) ); // true console.log( pattern.test( text ) ); // false (文字列の末尾でマッチしないと、lastIndexは0にリセットされる) console.log( pattern.test( text ) ); // true (lastIndexがリセットされたことにより、再びマッチする)
このことからexec()と混在して用いると、予期せぬ結果となることがあります。
var text = '123'; var pattern = /[0-9]/g; console.log( pattern.test( text ) ); // true // ここでlastIndexは1となっている console.log( pattern.exec( text ) ); // 2 (2文字目からマッチしている) console.log( pattern.exec( text ) ); // 3 console.log( pattern.exec( text ) ); // null
よって正規表現オブジェクトを使い回す場合は、明示的にlastIndexをリセットするようにします。
var text = '123'; var pattern = /[0-9]/g; console.log( pattern.test( text ) ); // true pattern.lastIndex = 0; // lastIndexをリセットする console.log( pattern.exec( text ) ); // 1 (1文字目からマッチしている) console.log( pattern.exec( text ) ); // 2 console.log( pattern.exec( text ) ); // 3
指定文字のいずれかにマッチする、文字クラスがサポートされます。
文字クラスの略記法もサポートされます。
メタ文字を文字列リテラルで記述するときは、エスケープが必要です。
メタ文字 ※1 | 意味 | 別表記 |
---|---|---|
\d |
任意の数字 (Decimal digit) | [0-9] |
\w |
任意の単語文字 (Word) | [a-zA-Z0-9_] |
\s |
任意のUnicode空白文字 (White space) | [ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000] ※2 |
※1 メタ文字を大文字にすると、それを否定した意味になります。
※2 幅ゼロの空白文字、\u200B
と\uFEFF
は含まれません。
メタ文字に不足する文字がある場合には、全体を[]で囲み文字を追加します。
/[\da-z]/
Perlの正規表現と比較して、次の機能が使用できません。
\a
、\e
、\l
、\u
、\L
、\U
、\E
、\Q
、\A
、\Z
、\z
、\G
(?
拡張構文の一部
(?<=
(?<!
(?#
正規表現リテラルにスラッシュを記述するには、それをエスケープする必要があります。
/\//.test( 'SAMPLE/' )
同様の処理でも、RegExpのコンストラクタで記述する場合には、エスケープは不要です。
new RegExp( '/' ).test( 'SAMPLE/' )
文字列リテラルと正規表現リテラルでは、文字列中のバックスラッシュの扱いが異なります。よってこの2つを書き換える際には、注意が必要です。
たとえば「?」という記号にマッチさせる場合を考えます。これは量指定子のメタ文字であるため、
/\?/
のように、正規表現ではこれをバックスラッシュでエスケープする必要があります。一方でこの表現をそのまま文字列リテラルに当てはめて、
new RegExp( '\?' )
とすると、「SyntaxError: invalid quantifier」の例外が発生します。これは「\?
」というエスケープシーケンスが存在しないため「?
」と解釈され、結果として不正な正規表現となっているためです。
このとき文字列リテラルにバックスラッシュを記述するには「\\
」とすることを踏まえると、正しくは
new RegExp( '\\?' )
とすべきことがわかります。
文字列リテラルにバックスラッシュを記述するにはエスケープが必要であり、かつバックスラッシュにマッチさせるためにもエスケープが必要であることから、バックスラッシュにマッチさせるためには、
new RegExp( '\\\\' )
のように記述します。一方で正規表現リテラルで記述するときはバックスラッシュのエスケープは不要なため、
/\\/
とします。≫PHPの正規表現でバックスラッシュにマッチさせる方法