この大幅に改善された回答は、@EliGassertによるものです。
String.prototype.match_overlap = function(re)
{
if (!re.global)
re = new RegExp(re.source,
'g' + (re.ignoreCase ? 'i' : '')
+ (re.multiline ? 'm' : ''));
var matches = [];
var result;
while (result = re.exec(this))
matches.push(result),
re.lastIndex = result.index + 1;
return matches.length ? matches : null;
}
@EliGassertは、文字列全体を文字ごとにウォークスルーする必要はないことを指摘しています。代わりに、どこでも一致を見つけることができ(つまり、アンカーなしで行う)、見つかった一致のインデックスの後に1文字続けます。上記のインデックスを取得する方法を調査しているときに、検索を続行する場所を追跡するためre.lastIndex
に使用されるプロパティが実際に設定可能であることがわかりました。これは、私たちがやろうとしていることとかなりうまく機能します。exec
さらに説明が必要なのは始まりだけかもしれません。g
フラグがない場合、はexec
決して戻らないnull
可能性があり(存在する場合は常に1つの一致を返す)、したがって無限ループに入る可能性があります。ただし、match_overlap
設計上、複数の一致を求めるため、非グローバルを グローバルRegExp
として安全に再コンパイルし、設定されている場合はオプションとオプションもインポートできます。 RegExp
i
m
新しいjsFiddleは次のとおりです:http://jsfiddle.net/acheong87/h5MR5/。
document.write("<pre>");
document.write('sasas'.match_overlap(/sas/));
document.write("\n");
document.write('aaaa'.match_overlap(/aa/));
document.write("\n");
document.write('my1name2is3pilchard'.match_overlap(/[a-z]{2}[0-9][a-z]{2}/));
document.write("</pre>");
出力:
sas,sas
aa,aa,aa
my1na,me2is,is3pi