5

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

[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>');     
}
4

3 回答 3

7

试试这个正则表达式:

/\[(.+?)\]\((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 开头的行。

于 2013-01-30T08:02:39.563 回答
5
str.replace(/\[(.*?)\]\((.*?)\)/gi, '<a href="$2">$1</a>');

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

然后:

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

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

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

于 2013-01-30T08:02:19.113 回答
3

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

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

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

The regex above should capture some part (I'm not confident it captures everything, the source code of Pagedown is too complex to read in one go) of the behavior of Pagedown for [description](url) style of linking (title is not supported). The regex above is mixed from 2 different regex used in the Pagedown source code.

Some features:

  • Capturing group 1 contains text inside [] and capturing group 2 contains the URL.
  • Allow escaping of [ and ] inside the text part [], by using \ e.g. [a\[1\]](http://link.com). You need to do a bit of extra processing, though.
  • Allow 1 level of () inside link, very useful in cases like this: [String.valueOf](http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#valueOf(double))
  • Allow space after the link and before the ).

I don't take into account the bare link in this regex.

Reference:

于 2013-01-30T12:28:32.110 回答