您的[^<>]
开头是一个消费模式,它匹配除<
和>
之外的任何字符,并且可以匹配更多,然后只是一个换行符。你把这个char放入href
的值与匹配字符串的其余部分。
相反,占领模式的其余部分:
/(^|[^<>])\b((?:https?|ftp):\/\/[a-z0-9+&@#\/%?=~_|!:,.;-]*[a-z0-9-+&@#\/%=~_|])(?![^<>])/gi
^^^^^^^^^^ ^
的(^|[^<>])
将是第1组,其余的将被捕获到2组使用$1
和$2
反向引用在替换模式把捕获的部分到相应的地方:
function repl(text) {
var exp = /(^|[^<>])\b((?:https?|ftp):\/\/[a-z0-9+&@#\/%?=~_|!:,.;-]*[a-z0-9-+&@#\/%=~_|])(?![^<>])/gi;
return text.replace(exp, '$1<a href="$2">$2</a>');
}
对于一个更全面的URL提取的正则表达式,见How can i extract URL's from a piece of text into an Array using JavaScript与Diego Perini's URL regex用法示例。你可以调整它作为shown here:
s.replace(/(^|[^<>])\b((?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)[email protected])?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[\/?#]\S*)?)(?![<>])/gi, '$1<a href="$2">$2</a>')
一个更简单的,并且通常工作替代是协议到非后向除空白和<
/>
(尽可能多的与*
量词)以外的任何字符匹配字字符(感谢\b
字边界):
s.replace(/(^|[^<>])\b((?:https?|ftp):\/\/[^<>\s]+\b)/gi, '$1<a href="$2">$2</a>')
见regex demo here
我现在效果更好,但它似乎只匹配最后一个URL。如何替换(链接)textarea中的所有网址? – Roy
使用更好的正则表达式,检查很多其他职位上SO:[*正则表达式查找字符串中的URL *](http://stackoverflow.com/questions/6038061/regular-expression-to-find-urls-within -a-string)可能会有所帮助。我只是试图解决你的问题中描述的主要问题。 –
另一种方法是使用['.replace(/(^ | [^ <>])\ b((?:https?| ftp):\/\/[^ <> \ s] + \ b)/ gi ,'$ 1 $2')'](https://regex101.com/r/jWRHc1/1)。 –