String.prototype.match() と RegExp.prototype.exec() の比較
typescriptにおけるパターンマッチングの手法として、String.prototype.match()
と RegExp.prototype.exec()
がある。どちらも正規表現によるパターンマッチングを行うためのメソッドだが、一応ちょっとした違いがある。
1. String.prototype.match()
match()
は、文字列に対して呼び出され、指定した正規表現に一致する部分を検索する。ちなみにグローバルフラグ (/g
) を持つかどうかで、返す値が異なってくる。
例1: グローバルフラグなし
const content = 'random word[!image](path/to/image.png)random word';
const imageKeyRegex = /\[!image\]\((.*?)\)/;
const match = content.match(imageKeyRegex);
console.log(match);
// ["[!image](path/to/image.png)", "path/to/image.png"]
この例では、match
は配列として返され、最初の要素には一致した全体の文字列が、2番目の要素にはマッチした内容が入る。
例2: グローバルフラグあり
const content = 'random word[!image](path/to/image.png)random word';
const imageKeyRegex = /\[!image\]\((.*?)\)/g;
const matches = content.match(imageKeyRegex);
console.log(matches);
// ["[!image](path/to/image.png)"]
/g
フラグを指定すると、match()
は一致した全体の文字列の配列を返して、特定のマッチした部分は無視される。(あんまし使う場面が思いつかない)
2. RegExp.prototype.exec()
exec()
メソッドは、正規表現に対して呼び出され、文字列中で一致する部分を検索する。こっちのメソッドでは、常に次のマッチを返し、繰り返し呼び出すことで次々にマッチを見つけていく。良くある抽出のユースケースだとこちらを使えば良さそう。
const content = 'random word[!image](path/to/image.png)random word';
const imageKeyRegex = /\[!image\]\((.*?)\)/;
const match = imageKeyRegex.exec(content);
console.log(match);
// ["[!image](path/to/image.png)", "path/to/image.png"]
この場合、exec() は配列を返し、match[0] には全体のマッチ、match[1] にはキャプチャグループのマッチが入る。
主な違い?
メソッド | 対象 | 戻り値 | 繰り返し呼び出し | グローバルフラグ (/g ) の挙動 |
---|---|---|---|---|
String.prototype.match() |
文字列 | グローバルフラグなし: 全体とキャプチャグループの配列 グローバルフラグあり: 全体のマッチのみの配列 |
不可 | グローバルフラグがある場合、全体のマッチのみ返す |
RegExp.prototype.exec() |
正規表現 | 全体とキャプチャグループの詳細な情報を含む配列 | 可能 | 繰り返し呼び出すことで次々にマッチを取得可能 |
結論として、基本的に同じ挙動をするので好きな方を使えばいい感じだった。個人的にはmatch()
のが直感的に何やってるのか分かるので好み。
それにしても、パスだけが欲しい場合、どちらの場合でもmatch[1]
になってちょっぴり違和感がある