正規表現にマッチしたすべての文字列を取得する(String.prototype.match)

String オブジェクトのインスタンスメソッドである match は、対象の文字列が正規表現とマッチした場合、マッチした部分の文字列を取得します。また正規表現のパターンにキャプチャグループが含まれていた場合は、キャプチャグループにマッチした文字列も併せて取得します。グローバルフラグを設定した場合は、対象の文字列にマッチしたすべての文字列を一度に取得することもできます。ここでは String オブジェクトの match メソッドの使い方について解説します。

(Last modified: )

matchメソッドの使い方

String オブジェクトの match メソッドは、対象となる文字列が正規表現とマッチした場合に、マッチした文字列を取得します。書式は次の通りです。

文字列.match(正規表現オブジェクト)

文字列が引数に指定した正規表現とマッチした場合は、マッチした文字列が格納された配列を返します。マッチしなかった場合は null を返します。戻り値の配列にはインデックス 0 の要素にパターン全体にマッチした文字列、インデックス 1 以降の要素には設定したキャプチャグループで囲んだパターンにマッチした文字列が格納されます。(キャプチャグループを設定していない場合はインデックス 1 以降の要素は存在しません)。

配列[0]  パターン全体にマッチした文字列
配列[1]  キャプチャグループ1にマッチした文字列
配列[2]  キャプチャグループ2にマッチした文字列
・・・
配列[n]  キャプチャグループnにマッチした文字列

次のサンプルをみてください。最初にキャプチャグループが含まれないパターンの場合です。

let regexp = /20\d{2}-\d{2}-\d{2}/;
let str1 = 'Today is 2020-08-14';
let str2 = 'Yesterday is 1998-12-07';

let result1 = str1.match(regexp);
console.log(result1[0]);
>> 2020-08-14

let result2 = str2.match(regexp);
console.log(result2[0]);
>> TypeError: Cannot read property '0' of null

文字列が正規表現にマッチした場合には、パターン全体がマッチした文字列がインデックス 0 の要素の値として格納された配列として受け取ります。ただマッチしなかった場合には戻り値は null となり、 null に対してインデックス 0 の要素を取得しようとすると TypeError が発生します。次のように null かどうかの条件分岐を追加するか例外処理を行ってください。

let regexp = /20\d{2}-\d{2}-\d{2}/;
let str = 'Yesterday is 1998-12-07';

let result = str.match(regexp);
try{
  console.log(result[0]);
} catch(e) {
  console.log('Not Match');
}

>> Not Match

パターンにキャプチャグループが含まれる場合

続いてパターンにキャプチャグループが含まれている場合です。キャプチャグループを作成するには、パターンの中を括弧()で囲います。するとキャプチャグループに設定したパターンの部分にマッチした文字列を取得することができます。

※ キャプチャグループについては「キャプチャグループを設定してパターンの一部にマッチした文字列を取得する」を参照されてください。

次のサンプルを見てください。

let regexp = /(20\d{2})-(\d{2})-(\d{2})/;
let str = 'Today is 2020-08-14';

let result = str.match(regexp);
for (let i = 0 ; i < result.length ; i++){
  console.log('i=' + i + ', match=' + result[i]);
}

>> i=0, match=2020-08-14
>> i=1, match=2020
>> i=2, match=08
>> i=3, match=14

文字列が正規表現にマッチした場合は、戻り値として配列を受け取ります。インデックス 0 の要素にはパターン全体がマッチした文字列が格納され、インデックス 1 以降の要素にはそれぞれキャプチャグループで囲まれたパターンにマッチした文字列が格納されています。

今回はキャプチャグループが 3 つパターンに含まれているので、インデックス 1 からインデックス 3 までの要素にそれぞれキャプチャした文字列が格納されています。

パターンに名前付きキャプチャグループが含まれる場合

JavaScript では名前付きキャプチャグループも利用することができます。書式は次の通りです。

(?<グループ名>パターン)

名前のないキャプチャグループの場合、 match メソッドの戻り値である配列に含まれるインデックス 1 以降の要素の値を参照することでキャプチャした文字列を取得することができましたが、名前付きキャプチャグループでキャプチャした文字列は次の書式で参照することができます。

配列.groups.グループ名

次のサンプルを見てください。

let regexp = /(?<year>20\d{2})-(?<month>\d{2})-(?<day>\d{2})/;
let str = 'Today is 2020-08-14';

let result = str.match(regexp);
let year = result.groups.year;
let month = result.groups.month;
let day = result.groups.day;

console.log(year + '年' + month + '月' + day + '日');
>> 2020年08月14

名前付きキャプチャグループのキャプチャをそれぞれ取得し、 1 つの文字列にまとめて出力しました。できることは名前付きであっても名前がなくても同じですがキャプチャグループの番号で指定するよりもグループ名で指定してキャプチャを取得下方が分かりやすいコードにはなるかと思います。

マッチした文字列の位置を参照する

match メソッドを実行して文字列が正規表現にマッチした場合、マッチした文字列の先頭文字のインデックスが戻り値として取得した配列の index プロパティに設定されます。そこで index プロパティを参照することでマッチした文字列の位置を参照することができます。インデックスは対象の文字列の先頭文字が 0 、次の文字が 1 、と続いていきます。

次のサンプルをみてください。

let regexp = /20\d{2}-\d{2}-\d{2}/;
let str = 'Today is 2020-08-14';

let result = str.match(regexp);
console.log(result[0]);
>> 2020-08-14
console.log(result.index);
>> 9

マッチした文字列の位置を参照する(1)

対象の文字列の中で、正規表現にマッチした文字列の先頭文字のインデックスを参照することができました。

グローバルフラグが設定されている場合

パターンの最後に g を記述するとグローバルフラグを設定することができます。

/パターン/g

正規表現にグローバルフラグが設定されている場合、 match メソッドを実行すると対象の文字列の中で正規表現がマッチするすべての文字列が格納された配列を返します。グローバルフラグが設定されている場合はパターンにキャプチャグループが設定されていてもキャプチャは取得することができません。

次のサンプルを見てください。

let regexp = /[A-Z].+?day/g;
let str = 'Sunday Monday Tuesday';

let result = str.match(regexp);
for (let i = 0 ; i < result.length ; i++){
  console.log(result[i]);
}

>> Sunday
>> Monday
>> Tuesday

対象の文字列の中でパターンに一致するすべての文字列を取得することができました。

-- --

String オブジェクトの match メソッドの使い方について解説しました。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。