6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年11月29日 JavaScript (JS Primer) 正規表現

マッチした文字列の一部を取得

キャプチャリング

キャプチャリングとは、正規表現中で/パターン1(パターン2)/のようにカッコで囲んだ部分を取り出すことです。 String#matchメソッドとString#matchAllメソッドはどちらもキャプチャリングに対応しています。

const [マッチした全体の文字列, キャプチャ1, キャプチャ2] = 文字列.match(/パターン(キャプチャ1)(キャプチャ2)/);

String#matchメソッドとString#matchAllメソッドで 正規表現パターンに一致する文字列を検索した上で、その中でさらに正規表現パターンを絞って取得したい場合にキャプチャリングを利用します。

キャプチャリングした場合、返り値は0番目がマッチした全体、1番目がキャプチャの1番目というようになります。

// "ECMAScript (数字+)"にマッチするが、欲しい文字列は数字の部分のみとします。
const pattern = /ECMAScript (\d+)(\d+)/;

// 返り値は[マッチした全部の文字列, キャプチャの1番目, キャプチャの2番目 ....]というふうになります。
const [all, capture1, capture2] = "ECMAScript 67".match(pattern);
console.log(all); // => "ECMAScript 67"
console.log(capture1); // => "6"
console.log(capture2);// => "7"

primerの例となっていたコードにキャプチャ2を追記してみました。
こうして実際にprimerのコンソール内でコードを書き挙動を確かめると理解が深まるのでおすすめです。  

String#matchAllの場合

String#matchメソッドはgフラグを使用し繰り返しマッチさせる処理を行なった場合に、それぞれ個別のマッチした情報を取得できませんが、String#matchAllメソッドはイテレータを返すためキャプチャリングした上で繰り返し処理を行うことが出来ます。

次のコードではESのあとの数字をそれぞれキャプチャリングしたものがcapture1に代入されています。

// "ES(数字+)"にマッチするが、欲しい文字列は数字の部分のみ
const pattern = /ES(\d+)/g;
// iteratorを返す
const matchesIterator = "ES2015、ES2016、ES2017".matchAll(pattern);
console.log(matchesIterator);
for (const match of matchesIterator) {
    // マッチした要素ごとの情報を含んでいます。
    // 0番目はマッチした文字列全体、1番目がキャプチャの1番目である数字です。
    console.log(`match: "${match[0]}", capture1: ${match[1]}, index: ${match.index}, input: "${match.input}"`);
}
// 次の順番でコンソールに出力されます。
// match: "ES2015", capture1: 2015, index: 0, input: "ES2015、ES2016、ES2017"
// match: "ES2016", capture1: 2016, index: 7, input: "ES2015、ES2016、ES2017"
// match: "ES2017", capture1: 2017, index: 14, input: "ES2015、ES2016、ES2017"

参考  

数値とマッチする正規表現 正規表現フラグ