【初心者向け】JavaScriptのRegExpで複数回検索を行う方法:グローバルフラグ(gフラグ)とexecメソッド、matchメソッド、replaceメソッド


グローバルマッチングとは

正規表現オブジェクトがregExp.globalフラグを持つ場合、その正規表現はテキスト内のすべてのマッチング箇所を見つけようとします。一方、フラグがない場合は、最初にマッチングする箇所のみを見つけます。

const text = "JavaScript is a programming language.";
const regex = /Java/g; // 'g'フラグを指定

console.log(regex.exec(text)); // ["Java"]
console.log(regex.exec(text)); // ["Java"]

この例では、regexオブジェクトはJavaというパターンを持つように定義されています。gフラグが指定されているため、text内にあるすべてのJavaというパターンを見つけようとします。

regExp.globallastIndexプロパティ

regExp.globalフラグを使用する場合、RegExpオブジェクトにはlastIndexプロパティが追加されます。このプロパティは、次のマッチング箇所を探す開始位置を保存します。

const text = "JavaScript is a JavaScript language.";
const regex = /Java/g;

console.log(regex.exec(text)); // ["Java"]
console.log(regex.lastIndex); // 6

console.log(regex.exec(text)); // ["Java"]
console.log(regex.lastIndex); // 16

この例では、最初のマッチング箇所が見つかった後、lastIndexプロパティは6に設定されます。2回目のマッチングでは、lastIndexプロパティから開始するため、2番目のJavaというパターンが見つかります。

regExp.globalのメリット

  • ループ処理で個別にマッチング箇所を探す必要がない
  • テキスト内のすべてのマッチング箇所を見つけられる
  • 必要なマッチング箇所のみを見つけたい場合は、regExp.globalフラグを使用しない方が効率的
  • すべてのマッチング箇所を探すため、処理時間が長くなる可能性がある


const text = "JavaScript 101 is a programming language. I love 123!";
const regex = /\d+/g; // 'g'フラグを指定

const matches = [];
let match;

while ((match = regex.exec(text)) !== null) {
  matches.push(match[0]);
}

console.log(matches); // ["101", "123"]

このコードでは、regexオブジェクトは\d+というパターンを持つように定義されています。このパターンは、1つ以上の数字に一致します。gフラグが指定されているため、text内にあるすべての数字を見つけようとします。

ループ処理を使用して、regex.exec()メソッドを繰り返し呼び出し、マッチング箇所を見つけます。exec()メソッドは、マッチング箇所が見つかった場合は配列を返し、見つからなかった場合はnullを返します。

マッチング箇所が見つかったら、その値をmatches配列にプッシュします。ループ処理が終了すると、matches配列にはテキスト内のすべての数字が格納されます。

以下は、regExp.global フラグを使用して、特定の文字列をすべて大文字に変換する方法を示しています。

const text = "Hello, world!";
const regex = /[a-z]/g; // 小文字の英字にマッチ

const transformedText = text.replace(regex, function(match) {
  return match.toUpperCase();
});

console.log(transformedText); // "HELLO, WORLD!"

このコードでは、regexオブジェクトは[a-z]というパターンを持つように定義されています。このパターンは、小文字の英字に一致します。gフラグが指定されているため、text内にあるすべて小文字の英字を見つけようとします。

replace()メソッドを使用して、regexオブジェクトにマッチするすべての文字列を大文字に変換します。replace()メソッドは、最初の引数として正規表現オブジェクト、2番目の引数として置換文字列または置換関数を指定します。

この例では、置換関数を使用して、マッチングした文字列を大文字に変換しています。置換関数は、マッチングした文字列を単一の引数として受け取り、変換後の文字列を返す必要があります。

regExp.global フラグは、テキスト内のすべてのマッチング箇所を見つけるのに役立ちます。ループ処理で個別にマッチング箇所を探す必要がなくなり、コードを簡潔に記述できます。



しかし、状況によっては regExp.global フラグを使用するよりも、代替方法の方が効率的だったり、コードが読みやすくなったりする場合があります。

以下に、regExp.global の代替方法をいくつか紹介します。

while ループと RegExp.exec() メソッドを使用する

最も基本的な代替方法は、while ループと RegExp.exec() メソッドを使用して、テキスト内のすべてのマッチング箇所を個別に探していく方法です。

const text = "JavaScript 101 is a programming language. I love 123!";
const regex = /\d+/; // 'g'フラグは不要

const matches = [];
let match;

while ((match = regex.exec(text)) !== null) {
  matches.push(match[0]);
}

console.log(matches); // ["101", "123"]

このコードは regExp.global フラグを使用していないものの、while ループと exec() メソッドを使用して、テキスト内のすべての数字を見つけることができます。

String.match() メソッドを使用する

String.match() メソッドは、テキスト内のすべてのマッチング箇所を配列として返します。このメソッドは、regExp.global フラグと同様に、テキスト内のすべてのマッチング箇所を見つけることができます。

const text = "JavaScript 101 is a programming language. I love 123!";
const regex = /\d+/; // 'g'フラグは不要

const matches = text.match(regex);

console.log(matches); // ["101", "123"]

このコードは、regExp.global フラグを使用していないものの、match() メソッドを使用して、テキスト内のすべての数字を見つけることができます。

String.replace() メソッドと置換関数を使用する

String.replace() メソッドは、テキスト内のすべてのマッチング箇所を置換文字列または置換関数で置き換えます。置換関数を使用して、マッチング箇所ごとに処理を行うことができます。

const text = "Hello, world!";
const regex = /[a-z]/; // 'g'フラグは不要

const transformedText = text.replace(regex, function(match) {
  return match.toUpperCase();
});

console.log(transformedText); // "HELLO, WORLD!"

このコードは、regExp.global フラグを使用していないものの、replace() メソッドと置換関数を使用して、テキスト内のすべて小文字の英字を大文字に変換することができます。

正規表現エンジンライブラリを使用する

JavaScript には、PCREOnigmo などの正規表現エンジンライブラリがいくつか存在します。これらのライブラリは、より高度な機能を提供しており、regExp.global フラグの代替手段として使用することができます。