Javascript Regexp循环所有匹配

时间:2011-04-29 17:42:32

标签: javascript regex loops match

我正在尝试使用堆栈溢出的富文本编辑器做类似的事情。鉴于此文:

[Text Example][1]

[1][http://www.example.com]

我想循环找到的每个[string][int]

var Text = "[Text Example][1]\n[1][http: //www.example.com]";
// Find resource links
var arrMatch = null;
var rePattern = new RegExp(
  "\\[(.+?)\\]\\[([0-9]+)\\]",
  "gi"
);
while (arrMatch = rePattern.exec(Text)) {
  console.log("ok");
}

这很好用,它会为每个[string][int]提醒'确定'。我需要做的是,对于找到的每个匹配,用第二个匹配的组件替换初始匹配。

所以在循环中$ 2代表最初匹配的int部分,我会运行这个regexp(pseduo)

while (arrMatch = rePattern.exec(Text)) {
    var FindIndex = $2; // This would be 1 in our example
    new RegExp("\\[" + FindIndex + "\\]\\[(.+?)\\]", "g")

    // Replace original match now with hyperlink
}

这将匹配

[1][http://www.example.com]

第一个例子的最终结果是:

<a href="http://www.example.com" rel="nofollow">Text Example</a>

修改

我现在已经达到了这个目标:

var Text = "[Text Example][1]\n[1][http: //www.example.com]";
// Find resource links
reg = new RegExp(
  "\\[(.+?)\\]\\[([0-9]+)\\]",
  "gi");
var result;
while ((result = reg.exec(Text)) !== null) {
  var LinkText = result[1];
  var Match = result[0];
  Text = Text.replace(new RegExp(Match, "g"), '<a href="#">" + LinkText + "</a>');
}
console.log(Text);

7 个答案:

答案 0 :(得分:37)

我同意杰森认为使用现有的Markdown库更快/更安全,但你正在寻找String.prototype.replace(同样,使用RegExp文字!):

var Text = "[Text Example][1]\n[1][http: //www.example.com]";
var rePattern = /\[(.+?)\]\[([0-9]+)\]/gi;

console.log(Text.replace(rePattern, function(match, text, urlId) {
  // return an appropriately-formatted link
  return `<a href="${urlId}">${text}</a>`;
}));

答案 1 :(得分:33)

我最终设法做到了这一点:

var Text = "[Text Example][1]\n[1][http: //www.example.com]";
// Find resource links
reg = new RegExp(
  "\\[(.+?)\\]\\[([0-9]+)\\]",
  "gi");
var result;
while (result = reg.exec(Text)) {
  var LinkText = result[1];
  var Match = result[0];
  var LinkID = result[2];
  var FoundURL = new RegExp("\\[" + LinkID + "\\]\\[(.+?)\\]", "g").exec(Text);
  Text = Text.replace(Match, '<a href="' + FoundURL[1] + '" rel="nofollow">' + LinkText + '</a>');
}
console.log(Text);

答案 2 :(得分:3)

这里我们使用 exec 方法,它有助于获得所有匹配(使用while while循环)并获取匹配字符串的位置。

    var input = "A 3 numbers in 333";
    var regExp = /\b(\d+)\b/g, match;
    while (match = regExp.exec(input))
      console.log("Found", match[1], "at", match.index);
    // → Found 3 at 2 //   Found 333 at 15 

答案 3 :(得分:0)

此格式基于Markdown。有several JavaScript ports可用。如果您不想要整个语法,那么我建议窃取与链接相关的部分。

答案 4 :(得分:0)

这是一个小例子,希望你能找到有用的东西。 正则表达式中使用\number来引用组匹配编号,并且在替换函数中使用$number来引用组结果,这样您就可以强制执行这些数字,如果您的文本是< / p>

[Text Example][1]\n[1][http://www.example.com]

它会匹配,如果它是

[Text Example][1]\n[2][http://www.example.com]

它不会

var re = /\[(.+?)\]\[([0-9]+)\s*.*\s*\[(\2)\]\[(.+?)\]/gi;
var str = '[Text Example][1]\n[1][http://www.example.com]';
var subst = '<a href="$4">$1</a>';

var result = str.replace(re, subst);
console.log(result);

答案 5 :(得分:0)

另一种不依赖exec和match细节而迭代所有匹配项的方法是使用字符串替换函数,该函数将regex作为第一个参数,将函数用作第二个参数。像这样使用时,函数参数将整个匹配项作为第一个参数,将分组的匹配项作为下一个参数,将索引作为最后一个参数:

var text = "[Text Example][1]\n[1][http: //www.example.com]";
// Find resource links
var arrMatch = null;
var rePattern = new RegExp("\\[(.+?)\\]\\[([0-9]+)\\]", "gi");
text.replace(rePattern, function(match, g1, g2, index){
    // Do whatever
})

您甚至可以使用全局JS变量arguments遍历每个匹配项的所有组,但不包括第一个和最后一个。

答案 6 :(得分:-2)

我知道它很旧,但由于我偶然发现了这篇文章,我想把事情搞清楚。

首先,你解决这个问题的思路太复杂了,当本该简单的问题的解决方案变得太复杂时,是时候停下来想想哪里出了问题。 其次,您的解决方案在某种程度上非常低效,您首先尝试找到要替换的内容,然后尝试在同一文本中搜索引用的链接信息。所以计算复杂度最终变成了O(n^2)

看到这么多人对错误的投票感到非常失望,因为来到这里的人主要从公认的解决方案中学习,认为这似乎是合法的答案并在他们的项目中使用这个概念,然后成为一个非常产品实施不当。

解决这个问题的方法非常简单。您需要做的就是在文本中找到所有引用的链接,将它们保存为字典,然后使用字典搜索要替换的占位符。而已。就这么简单!在这种情况下,您只会得到 O(n) 的复杂性。

事情是这样的:

const text = `
 [2][https://en.wikipedia.org/wiki/Scientific_journal][5][https://en.wikipedia.org/wiki/Herpetology]

The Wells and Wellington affair was a dispute about the publication of three papers in the Australian Journal of [Herpetology][5] in 1983 and 1985. The publication was established in 1981 as a [peer-reviewed][1] [scientific journal][2] focusing on the study of [3][https://en.wikipedia.org/wiki/Amphibian][amphibians][3] and [reptiles][4] ([herpetology][5]). Its first two issues were published under the editorship of Richard W. Wells, a first-year biology student at Australia's University of New England. Wells then ceased communicating with the journal's editorial board for two years before suddenly publishing three papers without peer review in the journal in 1983 and 1985. Coauthored by himself and high school teacher Cliff Ross Wellington, the papers reorganized the taxonomy of all of Australia's and New Zealand's [amphibians][3] and [reptiles][4] and proposed over 700 changes to the binomial nomenclature of the region's herpetofauna.
[1][https://en.wikipedia.org/wiki/Academic_peer_review]    
[4][https://en.wikipedia.org/wiki/Reptile]          
`;

const linkRefs = {};
const linkRefPattern = /\[(?<id>\d+)\]\[(?<link>[^\]]+)\]/g;
const linkPlaceholderPattern = /\[(?<text>[^\]]+)\]\[(?<refid>\d+)\]/g;

const parsedText = text
    .replace(linkRefPattern, (...[,,,,,ref]) => (linkRefs[ref.id] = ref.link, ''))
    .replace(linkPlaceholderPattern, (...[,,,,,placeholder]) => `<a href="${linkRefs[placeholder.refid]}">${placeholder.text}</a>`)
    .trim();

console.log(parsedText);