1. ホーム
  2. javascript

[解決済み] Javascriptのregex.exec()はなぜいつも同じ値を返さないのですか?重複

2022-05-27 04:10:19

質問

ChromeやFirebugのコンソールで。

reg = /ab/g
str = "abc"
reg.exec(str)
   ==> ["ab"]
reg.exec(str)
   ==> null
reg.exec(str)
   ==> ["ab"]
reg.exec(str)
   ==> null

exec は何らかのステートフルなもので、前回何を返したかに依存するのでしょうか?それともこれは単なるバグですか?私はそれが常に起こるようにすることはできません。例えば、上の'str'が"abc abc"だった場合、それは起きないのです。

どうすれば解決しますか?

JavaScript RegExp オブジェクトはステートフルです。

正規表現がグローバルな場合、同じ正規表現オブジェクトに対してメソッドを呼び出すと、最後にマッチした部分の過去のインデックスから開始されます。

これ以上マッチが見つからなくなると、インデックスがリセットされ 0 に自動的にリセットされます。


手動でリセットするには lastIndex プロパティを設定します。

reg.lastIndex = 0;


これは非常に便利な機能です。必要であれば、文字列の任意の位置で評価を開始することができますし、ループ内であれば、任意の数のマッチの後に評価を停止することができます。


以下は、ループ内で正規表現を使用する典型的なアプローチのデモです。これは exec が返す null をループ条件として代入し、マッチングが無くなれば

var re = /foo_(\d+)/g,
    str = "text foo_123 more text foo_456 foo_789 end text",
    match,
    results = [];

while (match = re.exec(str))
    results.push(+match[1]);

DEMO。 http://jsfiddle.net/pPW8Y/


課題の配置が気に入らない場合は、例えばこのようにループを作り直すことも可能です...。

var re = /foo_(\d+)/g,
    str = "text foo_123 more text foo_456 foo_789 end text",
    match,
    results = [];

do {
    match = re.exec(str);
    if (match)
        results.push(+match[1]);
} while (match);

DEMO。 http://jsfiddle.net/pPW8Y/1/