LoginSignup
4
1

More than 1 year has passed since last update.

【JavaScript】str.matchAll(re)はre.exec(str), re.test(str)の最後のマッチ位置を引き継ぐので注意

Last updated at Posted at 2021-07-12

正規表現が間違えてるのかと3時間ぐらい格闘して10キロ痩せた

re.exec(str)

普通に使ったら何回実行しても結果は同じ。

const re = /\d/;
const str = "abc123def";

re.exec(str)[0] // 1;
re.exec(str)[0] // 1;
re.exec(str)[0] // 1;

正規表現にgフラグをつけると実行するたびに次のマッチの結果が返ってくる。

const re = /\d/g;
const str = "abc123def";

re.exec(str)[0] // 1;
re.exec(str)[0] // 2;
re.exec(str)[0] // 3;

マッチするものがなくなったら一旦nullを返してまた最初から始まる。

const re = /\d/g;
const str = "abc123def";

re.exec(str)?.[0]; // 1
re.exec(str)?.[0]; // 2
re.exec(str)?.[0]; // 3
re.exec(str)?.[0]; // undefined
re.exec(str)?.[0]; // 1
re.exec(str)?.[0]; // 2

re.test(str)

こっちも同じ。
true/falseしか返ってこないので前回の位置を引き継いでるのが分かりにくい。

const re = /\d/g;
const str = "abc123def";

re.test(str); // true
re.test(str); // true
re.test(str); // true
re.test(str); // false
re.test(str); // true
re.test(str); // true

execと夢のコラボも実現

const re = /\d/g;
const str = "abc123def";

re.exec(str)[0]; // 1
re.test(str); // true
re.exec(str)[0]; // 3
re.test(str); // false

str.matchAll(re)

で、str.matchAll(re)もそれを引き継ぐ。
ちなみにstr.matchAll(re)に渡す正規表現はgフラグがついてないとエラーになる。

const re = /./g;
const str = "abcdef";

re.exec(str)[0]; // a
re.exec(str)[0]; // b

[...str.matchAll(re)].map(m=>m[0]);
// c, d, e, f

でもstr.matchには影響ないよ。
だからstr.matchAllにも影響ないんだと思ってた。

const re = /./g;
const str = "abcdef";

re.exec(str)[0]; // a
re.exec(str)[0]; // b

[...str.match(re)]
// a, b, c, d, e, f

「そうはならんやろ」って人、こんなんやりそうな感じしませんか。(やった)

const re = /\d/g;
const str = "abc123def";

// なんとなく負荷下がりそうだしそもそもマッチしないなら実行せんとこ
let matches;
if (re.test(str)) { //ここで「1」が消費される
  matches = [...str.matchAll(re)], // 2, 3
} else {
  matches = []
}

なっとる!!!!!!やろがい!!!!!!!!

4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1