5

我正在研究“哥德尔、埃舍尔、巴赫”第 2 章中的 MIU 系统问题。

其中一项规则规定

Rule III: If III occurs in one of the strings in your collection, you may make a new string with U in place of III.

这意味着字符串MIII可以变为MU,但对于其他更长的字符串,可能有多种可能性[括号中的匹配项]:

  • MIIII可以产生
    • M[III]I>>MUI
    • MI[III]>>MIU
  • MUIIIUIIIU可以产生
    • MU[III]UIIIU>>MUUUIIIU
    • MUIIIU[III]U>>MUIIIUUU
  • MUIIIIU可以产生
    • MU[III]IU>>MUUIU
    • MUI[III]U>>MUIUU

显然,诸如此类的正则表达式/(.*)III(.*)/很有帮助,但我似乎无法让它们生成所有可能的匹配,只是它碰巧找到的第一个匹配。

有没有办法生成所有可能的匹配?

(注意,我可以想办法完全手动执行此操作,但我希望使用内置工具、正则表达式或其他方式有更好的方法)

(编辑以澄清重叠的需求。)

4

2 回答 2

12

这是您需要的正则表达式:/III/g- 足够简单,对吧?现在这里是你如何使用它:

var text = "MUIIIUIIIU", find = "III", replace "U",
    regex = new RegExp(find,"g"), matches = [], match;
while(match = regex.exec(text)) {
    matches.push(match);
    regex.lastIndex = match.index+1;
}

regex.lastIndex...行覆盖了不匹配结果的通常正则表达式行为。此外,我正在使用RegExp构造函数来使其更加灵活。你甚至可以通过这种方式将它构建成一个函数。

现在你有一个匹配对象数组,你可以这样做:

matches.forEach(function(m) { // older browsers need a shim or old-fashioned for loop
    console.log(text.substr(0,m.index)+replace+text.substr(m.index+find.length));
});

编辑: 是一个演示上述代码的 JSFiddle。

于 2013-08-03T05:24:29.903 回答
2

有时正则表达式是矫枉过正的。在您的情况下,简单的indexOf也可以!

诚然,这是一个 hack,但您可以自己将其转换为漂亮、可重用的代码:

var s = "MIIIIIUIUIIIUUIIUIIIIIU";
var results = [];
for (var i = 0; true; i += 1) {
    i = s.indexOf("III", i);
    if (i === -1) {
        break;
    }
    results.push(i);
}
console.log("Match positions: " + JSON.stringify(results));

它可以很好地处理重叠,至少对我来说,indexOf看起来更简单。

于 2013-08-03T05:34:48.480 回答