キャプチャグループを設定してパターンの一部にマッチした文字列を取得する
正規表現のパターンの中にキャプチャグループを設定することで、パターン全体にマッチした文字列とは別に、パターンの中の一部分にマッチした文字列を取得することができます。ここでは JavaScript の正規表現でキャプチャグループを利用する方法について解説します。
(Last modified: )
キャプチャグループの設定とキャプチャの取得
正規表現のパターンの中でキャプチャグループを設定するには、設定したい部分を括弧()で囲んでください。
/abc(def)ghi/
ここで使用する括弧はグループ化の時に指定した括弧と同じものです。グループ化のためにパターンの一部を括弧で囲うと、キャプチャグループもあわせて設定されます。
例えば次のパターンを見てください。
const regexp = /\d{3}-\d{4}/;
文字列 '郵便番号は 123-4567 です' はこのパターンにマッチし、パターン全体がマッチする文字列は 123-4567 です。この時、パターンの中の \d{4} の部分にマッチした部分だけを取得するにはキャプチャグループを設定します。キャプチャグループを設定するには、パターンの中の設定したい部分を括弧で囲います。
const regexp = /\d{3}-(\d{4})/;
これで文字列がパターンにマッチした時、パターン全体に対してマッチした文字列 123-4567 とは別に、キャプチャグループの部分にマッチした 4567 を取得することができます。キャプチャグループにマッチした文字列をキャプチャと呼びます。
キャプチャグループは 1 つのパターンの中に複数設定することができます。
const regexp = /(\d{3})-(\d{4})/;
複数のキャプチャグループを設定した場合は、前から順番にキャプチャグループ 1 、キャプチャグループ 2 のように設定され、あとからキャプチャグループのインデックスを指定してキャプチャされた文字列を参照します。
簡単なサンプルで試してみます。
let regexp = /(\d{3})-(\d{4})/; let result = regexp.exec('郵便番号は 123-4567 です。'); console.log(result[0]); >> 123-4567 console.log(result[1]); >> 123 console.log(result[2]); >> 4567
キャプチャを行わないキャプチャグループを設定する
グループ化のための括弧であってもパターンの中で括弧()で囲われるとキャプチャグループが設定されます。キャプチャを利用する予定がない場合で、明示的にキャプチャを行いたくない場合には括弧()ではなく次のように記述することでキャプチャを行わないキャプチャグループを設定できます。
(?:パターン)
「(」と「)」で囲う代わりに「(?:」と「)」で囲います。この書式で囲んだ場合はグループ化としての機能は同じですがキャプチャは行われません。キャプチャグループの値を繰り返し処理などで順に取得したい場合などに、キャプチャが目的ではないグループに対して使用すると便利です。
簡単なサンプルで試してみます。
let regexp = /製品(?:Code|コード):([A-Z]{2})-(\d{2})/; let result = regexp.exec('製品コード:AZ-07'); console.log(result[1]); >> AZ console.log(result[2]); >> 07
今回の場合、 3 つのキャプチャグループが設定されていますが、最初のキャプチャグループはキャプチャを行わないように設定したため、キャプチャを順に取得すると 2 つ目のキャプチャグループと 3 つ目のキャプチャグループのキャプチャを取得しました。
名前付きキャプチャグループを使用する
JavaScript では ECMAScript 2018 (ES 9) から名前付きキャプチャグループが利用可能となりました。キャプチャグループ毎に名前を設定し、インデックスではなく名前を使ってキャプチャした値を参照することができます。書式は次の通りです。
(?<グループ名>パターン)
通常のキャプチャグループでは、 String オブジェクトの match メソッドの戻り値として取得する配列に対してインデックスを指定して要素の値を参照することでキャプチャグループのキャプチャした値を参照してきました。名前付きキャプチャグループの場合は、 match メソッドの戻り値として取得する配列に対して次のように名前を指定してキャプチャした値を参照できます。
配列.groups.グループ名
簡単なサンプルで試してみます。
let regexp = /製品コード:(?<section>[A-Z]{2})-(?<code>\d{2})/; let result = regexp.exec('製品コード:JP-82'); console.log(result.groups.section); >> JP console.log(result.groups.code); >> 82
キャプチャした値と同じ値にマッチするパターン
パターンの中でキャプチャグループを設定した場合、キャプチャグループでマッチした値を同じパターン内から参照し、既にキャプチャした値と同じ値にマッチするようにパターンに記述することができます。
参照する場合は、キャプチャ1の値を参照するには \1 、キャプチャ2の値を参照するには \2 のようにパターン内に記述します。
\キャプチャ番号
次のパターンでは 1 番目のキャプチャグループでキャプチャした値を後から参照しています。
const regexp = /(ABC).*\1/;
この場合、 ABC から始まり、任意の文字が 0 回以上続いたあと、 1 番目のキャプチャグループでキャプチャした値と同じ値が続くパターンとなります。 1 番目のキャプチャグループでキャプチャした値は ABC なので /ABC.*ABC/ というパターンと同じです。
簡単なサンプルで試してみます。
const regex = /<(.+)>.*<\/\1>/;
let result = regex.exec('AAA <div>BBB<span>CCC</span>DDD</div>EEE');
console.log(result[0]);
>> <div>BBB<span>CCC</span>DDD</div>
今回のサンプルでは最初に見つかったタグ(今回の場合は <div> )と同じ名前の閉じタグ(今回の場合は </div> )で囲まれた文字列にマッチしています。同じ名前の閉じタグを探すためにキャプチャした値を後から参照しています。
-- --
JavaScript の正規表現でキャプチャグループを利用する方法について解説しました。
( Written by Tatsuo Ikura )
著者 / TATSUO IKURA
これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。