【问题标题】:How can I write a javascript regular expression to replace hyperlinks in this format [*](*) with html hyperlinks?如何编写一个 javascript 正则表达式来用 html 超链接替换这种格式 [*](*) 的超链接?
【发布时间】:2013-01-30 07:56:08
【问题描述】:

我需要带有以下格式链接的解析文本:

[html title](http://www.htmlpage.com)
http://www.htmlpage.com
http://i.imgur.com/OgQ9Uaf.jpg

这两个字符串的输出是:

<a href='http://www.htmlpage.com'>html title</a>
<a href='http://www.htmlpage.com'>http://www.htmlpage.com</a>
<a href='http://i.imgur.com/OgQ9Uaf.jpg'>http://i.imgur.com/OgQ9Uaf.jpg</a>

字符串可以包含任意数量的这些链接,即:

[html title](http://www.htmlpage.com)[html title](http://www.htmlpage.com)
[html title](http://www.htmlpage.com)   [html title](http://www.htmlpage.com)
[html title](http://www.htmlpage.com) wejwelfj http://www.htmlpage.com

输出:

<a href='http://www.htmlpage.com'>html title</a><a href='http://www.htmlpage.com'>html title</a>
<a href='http://www.htmlpage.com'>html title</a>    <a href='http://www.htmlpage.com'>html title</a>
<a href='http://www.htmlpage.com'>html title</a> wejwelfj <a href='http://www.htmlpage.com'>http://www.htmlpage.com</a>

我有一个非常长的函数,它通过传递字符串 3 次来完成工作,但我无法成功解析这个字符串:

[This](http://i.imgur.com/iIlhrEu.jpg) one got me crying first, then once the floodgates were opened [this](http://i.imgur.com/IwSNFVD.jpg) one did it again and [this](http://i.imgur.com/hxIwPKJ.jpg). Ugh, feels. Gotta go hug someone/something.

为简洁起见,我将发布我尝试过的正则表达式,而不是整个查找/替换函数:

var matchArray2 = inString.match(/\[.*\]\(.*\)/g);

对于匹配[*](*),不起作用,因为[]()[]() 已匹配

真的是这样,我猜。一旦我进行了匹配,我就会搜索匹配的 () 和 [] 以解析出链接和链接文本并构建 href 标记。我从临时字符串中删除了匹配项,因此当我第二次查找普通超链接时我不匹配它们:

var plainLinkArray = tempString2.match(/http\S*:\/\/\S*/g);

我没有用正则表达式解析任何 html。我正在解析一个字符串并尝试输出 html。

编辑:我添加了它在事后解析第三个链接http://i.imgur.com/OgQ9Uaf.jpg 的要求。

我的最终解决方案(基于@Cerbrus 的回答):

function parseAndHandleHyperlinks(inString)
{
    var result = inString.replace(/\[(.+?)\]\((https?:\/\/.+?)\)/g, '<a href="$2">$1</a>');
    return result.replace(/(?: |^)(https?\:\/\/[a-zA-Z0-9/.(]+)/g, ' <a href="$1">$1</a>');     
}

【问题讨论】:

  • What have you tried?正如这里的许多人会告诉你的那样,用正则表达式解析 HTML ......那样疯狂,@ 987654323@ 当然,如果你必须处理它的唯一标记是可能的,但请研究替代方案
  • 我想不出that会有用的地方...
  • @jahroy:您看到这里的网址是如何制作的吗?让我给你一个提示:[title](url)[title][1] &lt;....&gt; [1]:url。像这样的解析器在论坛和其他类似的社区网站上很有用。
  • 另外,@EliasVanOotegem:尝试解释 HTML 文档和尝试将一种特定格式解析为 HTML 是有区别的。
  • @cerbrus:你说得对,我只是说 regexhtmlparse,所以我跳到错误的结论。但是,当我发表评论时,没有任何代码可以显示 OP 迄今为止尝试过的内容,所以我将评论保留原样

标签: javascript regex


【解决方案1】:

试试这个正则表达式:

/\[(.+?)\]\((https?:\/\/[a-zA-Z0-9/.(]+?)\)/g

var s = "[html title](http://www.htmlpage.com)[html title](http://www.htmlpage.com)\n\
[html title](http://www.htmlpage.com)   [html title](http://www.htmlpage.com)\n\
[html title](http://www.htmlpage.com) wejwelfj http://www.htmlpage.com";

s.replace(/\[(.+?)\]\((https?:\/\/[a-zA-Z0-9/.(]+?)\)/g, '<a href="$2">$1</a>');

正则表达式解释:

# /                   - Regex Start
# \[                  - a `[` character (escaped)
# (.+?)               - Followed by any amount of words, grouped, non-greedy, so it won't match past:
# \]                  - a `]` character (escaped)
# \(                  - Followed by a `(` character (escaped)
# (https?:\/\/
#   [a-zA-Z0-9/.(]+?) - Followed by a string that starts with `http://` or `https://`
# \)                  - Followed by a `)` character (escaped)
# /g                  - End of the regex, search globally.

现在() / []中的2个字符串被捕获,并放在以下字符串中:

'<a href="$2">$1</a>';

这适用于您的“有问题”字符串:

var s = "[This](http://i.imgur.com/iIlhrEu.jpg) one got me crying first, then once the floodgates were opened [this](http://i.imgur.com/IwSNFVD.jpg) one did it again and [this](http://i.imgur.com/hxIwPKJ.jpg). Ugh, feels. Gotta go hug someone/something."
s.replace(/\[(.+?)\]\((https?:\/\/[a-zA-Z0-9/.(]+?)\)/g, '<a href="$2">$1</a>')

// Result:

'<a href="http://i.imgur.com/iIlhrEu.jpg">This</a> one got me crying first, then once the floodgates were opened <a href="http://i.imgur.com/IwSNFVD.jpg">this</a> one did it again and <a href="http://i.imgur.com/hxIwPKJ.jpg">this</a>. Ugh, feels. Gotta go hug someone/something.'

更多“错误”输入示例:

var s = "[Th][][is](http://x.com)\n\
    [this](http://x(.com)\n\
    [this](http://x).com)"
s.replace(/\[(.+?)\]\((https?:\/\/[a-zA-Z0-9/.(]+?)\)/g, '<a href="$2">$1</a>')

//   "<a href="http://x.com">Th][][is</a>
//    <a href="http://x(.com">this</a>
//    <a href="http://x">this</a>.com)"

你不能真的责怪最后一行的中断,因为没有办法知道用户是否打算在那里停止 url。

要捕获松散的网址,请添加以下内容:

.replace(/(?: |^)(https?\:\/\/[a-zA-Z0-9/.(]+)/g, ' <a href="$1">$1</a>');

(?: |^) 位捕获 String startspace 字符,因此它也会匹配以 url 开头的行。

【讨论】:

  • 是的,解析括号内的 href。在进行此替换后,我只是很难解析普通的href(因为这些新的超链接现在都是匹配的)。 @Explosion Pills 有一个解决方案,但它使用了 Javascript 不支持的后视。
  • [html title](http://www.htmlpage.com) wejwelfj http://www.htmlpage.com&lt;a href='http://www.htmlpage.com'&gt;html title&lt;/a&gt; wejwelfj &lt;a href='http://www.htmlpage.com'&gt;http://www.htmlpage.com&lt;/a&gt; 未处理。否则问题就解决了。
  • 啊,最后一个,我们不能检查一下http://前面有没有空格吗?像这样:s.replace(/(?: |^)(https?\:\/\/(\w|\.)+)/g, ' &lt;a href="$1"&gt;$1&lt;/a&gt;')。似乎对我有用。
  • 不幸的是,另一个测试用例是:http://www.htmlpage.com,链接周围根本没有空格。
  • 不幸的是,仍然没有做到这一点...此链接未正确解析,http://i.imgur.com/OgQ9Uaf.jpg 结果链接为i.imgur.com,正则表达式未捕获其余文本。请原谅我没有添加演示该示例的测试用例。
【解决方案2】:
str.replace(/\[(.*?)\]\((.*?)\)/gi, '<a href="$2">$1</a>');

这假定字符串中没有错误的括号或 URL 中的括号。

然后:

str.replace(/(\s|^)(https?:\/\/.*?)(?=\s|$)/gi, '$1<a href="$2">$2</a>')

这匹配一个类似“http”的 URL,该 URL 前面没有紧跟“”(之前的替换刚刚添加了该 URL)。当然,如果您有它,请随意使用更好的表达式。

编辑:我编辑了答案,因为我没有意识到 JS 没有后向语法。相反,您可以看到该表达式匹配任何空格 行的开头以匹配纯 http 链接。必须放回捕获的空间(因此是$1)。最后进行前瞻以确保捕获到下一个空格(或表达式末尾)的所有内容。如果空间对你来说不是一个好的边界,你将不得不想出一个更好的边界。

【讨论】:

  • 您的第一次替换会将标题和网址放在不正确的位置。
  • 第一个正则表达式似乎有效。当我使用它时,第二个显示“无效的限定符”: var result2 = result.replace(/(?$1'); Firefox 的错误控制台指向替换函数内部的初始 /。
  • 这似乎不起作用,因为 javascript 不支持“look-behind”。
  • 这个解决方案太松了。
  • @nhahtdh “太松”是什么意思?
【解决方案3】:

您似乎正在尝试将 Markdown 语法转换为 HTML。 Markdown 语法还没有一个规范(我指的是语法,而不是行为规范),所以你要蒙着眼睛四处走动,并尝试为你不想要的行为合并错误修复,所有的在重新发明轮子的同时。我建议您使用现有的实现而不是自己编写代码。例如,Pagedown 是 Markdown 的 JS 实现,目前在 StackOverflow 中使用。

如果您仍然需要正则表达式解决方案,以下是我的尝试。请注意,我不知道随着您的进步(如果您这样做的话),它是否会与 Markdown 的其他功能很好地配合。

/\[((?:[^\[\]\\]|\\.)+)\]\((https?:\/\/(?:[-A-Z0-9+&@#\/%=~_|\[\]](?= *\))|[-A-Z0-9+&@#\/%?=~_|\[\]!:,.;](?! *\))|\([-A-Z0-9+&@#\/%?=~_|\[\]!:,.;(]*\))+) *\)/i

上面的正则表达式应该捕获 [description](url) 链接样式的 Pagedown 行为的一部分(我不相信它会捕获所有内容,Pagedown 的源代码太复杂,无法一口气阅读)(标题不是支持的)。上面的正则表达式混合了 Pagedown 源代码中使用的 2 个不同的正则表达式。

一些功能:

  • 捕获组 1 包含 [] 内的文本,捕获组 2 包含 URL。
  • 允许在文本部分[] 中转义[],例如使用\ [a\[1\]](http://link.com)。不过,您需要做一些额外的处理。
  • 允许 1 级 () 内部链接,在这种情况下非常有用:[String.valueOf](http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#valueOf(double))
  • 在链接之后和) 之前留出空格。

我没有考虑这个正则表达式中的裸链接。

参考:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-08
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多