我不擅长常规exp。 我想将链接更改为文本中的超链接
例如
Hello http://stackoverflow.com
Hello www.stackoverflow.com
我希望stackoverflow链接
Hello <a href='http://stackoverflow.com'>http://stackoverflow.com</a>
Hello <a href='http://www.stackoverflow.com'>www.stackoverflow.com</a>
我用过这个
var exp = /(\b(https?|ftp|file|):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
return str.replace(exp,"<a href='$1' target='_blank'>$1</a>");
但这只适用于http://
提前感谢
答案 0 :(得分:6)
正如其他人所说,首先你需要定义什么是“链接”。 (请注意,“链接”仅是此上下文中“超链接”的缩写,因此您的句子没有意义。)考虑到您的两个示例,您希望匹配Uniform Resource Identifiers (URIs)和Fully Qualified Domain Names (FQDNs)代替。
为此,您应该使用RFC 3986, Appendix B -
中可以找到的正则表达式^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
- 并将其更改为与字边界匹配的一个,仅在//
之后接受FQDN和可选端口号,并在空白处停靠(\s
):
,----scheme----. ,-Fully Qualified Domain Name-.,-port.,--path--.,---query----.,fragment
| | | || || || || |
(^|\s)(([^:/?#\s]+):)?(//([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+(:\d+)?([^?#\s]*)(\?([^#\s]*))?(#(\S*))?
然后你可以使方案部分可选 -
|
v
(^|\s)((([^:/?#\s]+):)?//)?(([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+(:\d+)?([^?#\s]*)(\?([^#\s]*))?(#(\S*))?
- 并将其写为正则表达式文字(表达式中的斜杠需要在作为分隔符时进行转义):
/(^|\s)((([^:\/?#\s]+):)?\/\/)?(([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+)(:\d+)?([^?#\s]*)(\?([^#\s]*))?(#(\S*))?/
(您可能也希望匹配IDNs; JSX:regexp.js及其对Unicode字符属性的支持可以帮助您,请参阅How to remove all characters from a string。您可能希望预先添加到FQDN子表达式用于代理访问的URI (\w+@)?
中可选和不推荐的用户名传输的子表达式。)
然后您可以替换所有字符串(g
lobal修饰符),使其与相应的a
元素匹配:
var rx = /(^|\s)(((([^:\/?#\s]+):)?\/\/)?(([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+)(:\d+)?([^?#\s]*)(\?([^#\s]*))?(#(\S*))?)/g;
str = str.replace(rx,
function (match, optionalWhitespace, uri, scheme, p4, protocol, fqdn, p7, port,
path, query, queryVal, fragment, fragId) {
return (optionalWhitespace ? optionalWhitespace : '')
+ '<a href="' + (protocol ? uri : 'http://' + uri)
+ '" target="_blank">' + uri + '<\/a>';
});
您必须假设,当您只看到FQDN前缀时,它是非安全网站的域名,并且前缀为http://
。否则,href
属性中的URI引用将引用您的网站中可能存在的路径,该路径具有域名作为其名称(http://your-site.example/other-site.example.com
),这可能是不是你想要的。
这种表达式在你的情况下匹配太多是可能的,但不太可能;使用尽可能多的输入进行测试,并根据需要进行调整。如果向后兼容性不是问题,请使用non-capturing parentheses((?:…)
)来提高效率和减少命名参数;有关详细信息,请参阅ECMAScript Support Matrix。
捕获FQDN部分 - ([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+
周围的括号 - 是可选的;您可能希望使用它为a
元素提供class
属性值,以便以特殊方式对其进行格式化,例如预先设置适合的图标,例如链接到Stack Overflow,Wikipedia,Twitter,或Facebook。
您可能还想重新考虑使用target
属性(for Strict (X)HTML, you MUST remove it)。用户可能不善待无法控制链接目标的打开位置。提供标题,图标,光标等形式的提示。
答案 1 :(得分:0)
使用此代码:
var exp = /(((?:(?:https?|ftp|file):)?\/\/)?(?:[\w-]+\.)?[\w-]+\.\w{2,5}(?:\/[^\s\/]*)*)/ig;
return str.replace(exp, function(_, link, protocol){
return link.link(protocol ? link : "http://" + link);
});