Javascript正则表达式循环所有匹配
我正在尝试使用堆栈溢出的富文本编辑器做类似的事情。鉴于此文本:
[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]
发出“ok”警报。不过,我需要做的是,对于找到的每个匹配项,用第二个匹配项的组件替换初始匹配项。
因此,在循环中 $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);
I'm trying to do something similar with stack overflow's rich text editor. Given this text:
[Text Example][1]
[1][http://www.example.com]
I want to loop each [string][int]
that is found which I do this way:
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");
}
This works great, it alerts 'ok' for each [string][int]
. What I need to do though, is for each match found, replace the initial match with components of the second match.
So in the loop $2 would represent the int part originally matched, and I would run this 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
}
This would match
[1][http://www.example.com]
End result for first example would be:
<a href="http://www.example.com" rel="nofollow">Text Example</a>
Edit
I've gotten as far as this now:
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我同意 Jason 的观点,即使用现有的 Markdown 库会更快/更安全,但您正在寻找 String.prototype.replace (另外,使用 RegExp 文字!):
I agree with Jason that it’d be faster/safer to use an existing Markdown library, but you’re looking for String.prototype.replace (also, use RegExp literals!):
我最终成功做到了:
I managed to do it in the end with this:
这里我们使用 exec 方法,它有助于获取所有匹配项(在 while 循环的帮助下)并获取匹配字符串的位置。
Here we're using exec method, it helps to get all matches (with help while loop) and get position of matched string.
使用反向引用来限制匹配,以便如果您的文本是:,则代码将匹配;
如果您的文本是:,则代码将不匹配:
\number
在正则表达式中用于引用组匹配编号,$number
由替换函数以相同的方式使用,以引用组结果。Using back-references to to restrict the match so that the code will match if your text is:
and the code will not match if your text is:
\number
is used in regex to refer a group match number, and$number
is used by the replace function in the same way, to refer group results.此格式基于 Markdown。有多个 JavaScript 端口可用。如果您不想要整个语法,那么我建议窃取与链接相关的部分。
This format is based on Markdown. There are several JavaScript ports available. If you don't want the whole syntax, then I recommend stealing the portions related to links.
另一种迭代所有匹配而不依赖于 exec 和匹配微妙之处的方法是使用字符串替换函数,使用正则表达式作为第一个参数,使用函数作为第二个参数。当这样使用时,函数参数接收整个匹配作为第一个参数,分组匹配作为下一个参数,索引作为最后一个参数:
您甚至可以使用全局 JS 变量
arguments 迭代每个匹配的所有组
,不包括第一个和最后一个。Another way to iterate over all matches without relying on exec and match subtleties, is using the string replace function using the regex as the first parameter and a function as the second one. When used like this, the function argument receives the whole match as the first parameter, the grouped matches as next parameters and the index as the last one:
You can even iterate over all groups of each match using the global JS variable
arguments
, excluding the first and last ones.我知道它已经过时了,但自从我偶然发现这篇文章以来,我想把事情弄清楚。
首先,你解决这个问题的思维方式太复杂了,当看似简单的问题的解决方案变得太复杂时,是时候停下来思考哪里出了问题。
其次,您的解决方案在某种程度上效率非常低,您首先尝试找到要替换的内容,然后尝试在同一文本中搜索引用的链接信息。所以计算复杂度最终变成
O(n^2)
。看到这么多对错误的赞成票是非常令人失望的,因为来到这里的人们主要是从公认的解决方案中学习,认为这似乎是合法的答案,并在他们的项目中使用这个概念,然后该项目就变成了一个实施得很糟糕的产品。
解决这个问题的方法非常简单。您需要做的就是找到文本中所有引用的链接,将它们保存为字典,然后使用字典搜索要替换的占位符。就是这样。就是这么简单!在这种情况下,您的复杂度仅为
O(n)
。事情是这样的:
I know it's old, but since I stumble upon this post, I want to strait the things up.
First of all, your way of thinking into solving this problem is too complicated, and when the solution of supposedly simple problem becomes too complicated, it is time to stop and think what went wrong.
Second, your solution is super inefficient in a way, that you are first trying to find what you want to replace and then you are trying to search the referenced link information in the same text. So calculation complexity eventually becomes
O(n^2)
.This is very disappointing to see so many upvotes on something wrong, because people that are coming here, learning mostly from the accepted solution, thinking that this seems be legit answer and using this concept in their project, which then becomes a very badly implemented product.
The approach to this problem is pretty simple. All you need to do, is to find all referenced links in the text, save them as a dictionary and only then search for the placeholders to replace, using the dictionary. That's it. It is so simple! And in this case you will get complexity of just
O(n)
.So this is how it goes: