正如其他人所说,首先您需要定义什么是“链接”。(请注意,在这种情况下,“链接”只是“超链接”的缩写,因此您的这句话没有意义。)考虑到您的两个示例,您希望匹配统一资源标识符(URI)和完全限定域名(FQDN)代替。
为此,您应该采用可在RFC 3986 附录 B中找到的正则表达式-</p>
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
– 并将其更改为在单词边界处匹配的,在 之后仅接受 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*))?
然后你可以让方案部分成为可选的——</p>
|
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*))?/
(您可能也想匹配IDN;JSX:regexp.js 及其对 Unicode 字符属性的支持可以帮助您,请参阅如何从字符串中删除所有字符。您可能希望在 FQDN 子表达式前添加一个子表达式(\w+@)?
用于代理访问的 URI 中用户名的可选和不推荐传输。)
然后,您可以替换与相应元素匹配的所有字符串(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://
. 否则,属性中的 URI 引用将引用您href
网站中可能存在的路径,该路径以域名作为其名称 ( ),这可能不是您想要的。http://your-site.example/other-site.example.com
在您的情况下,此表达式可能匹配太多,但不太可能;使用尽可能多的输入进行测试,并根据需要进行调整。如果向后兼容性不是问题,请使用非捕获括号( (?:…)
) 以提高效率并减少命名参数;有关详细信息,请参阅ECMAScript 支持矩阵。
捕获 FQDN 部分(括号内([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+
)是可选的;您可能希望使用它为a
元素赋予class
属性值,以便以特殊方式对其进行格式化,例如添加合适的图标,例如用于指向 Stack Overflow、Wikipedia、Twitter 或 Facebook 的链接。
您可能还想重新考虑使用该target
属性(对于 Strict (X)HTML,您必须删除它)。用户可能不会善意地认为无法控制链接目标的打开位置。改为以标题、图标、光标等形式提供提示。