如何用JS正则识别非Markdown包裹的URL并转换为自动链接
可以实现,以下是两种可行的方案:
方案1:ES2018+ 环境(推荐,主流浏览器/Node.js 10+ 均支持)
利用JS支持的负向零宽后向断言,直接排除已经属于Markdown链接目标的URL,正则和示例代码如下:
// 匹配未被Markdown链接包裹的裸URL const urlRegex = /(?<!\[[^\]]*\]\()https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*[a-zA-Z0-9+#/])/g // 替换逻辑 const rawText = '你的原始文本内容' const formattedText = rawText.replace(urlRegex, (url) => `[${url}](${url})`)
规则说明
- 负向后向断言
(?<!\[[^\]]*\]\()确保当前URL的前面没有[xxx](结构,完美排除已经是Markdown链接目标的URL - 末尾的
[a-zA-Z0-9+#/]会自动过滤URL末尾的中文标点、英文逗号/句号等不属于URL的字符,避免把跟在URL后面的普通标点也放进链接里
方案2:兼容所有JS环境
如果需要适配不支持后向断言的老旧环境,可以用「全匹配+替换函数过滤」的方案,代码如下:
// 同时匹配Markdown链接和裸URL const matchRegex = /(\[[^\]]*\]\(https?:\/\/[^)]+\))|(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9]{1,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*[a-zA-Z0-9+#/]))/g // 替换逻辑 const rawText = '你的原始文本内容' const formattedText = rawText.replace(matchRegex, (match, markdownLink, rawUrl) => { // 如果匹配到的是已经格式化的Markdown链接,直接返回原值不处理 if (markdownLink) return markdownLink // 如果是裸URL,包装成Markdown链接 return `[${rawUrl}](${rawUrl})` })
原正则的问题说明
你当前使用的正则存在两个明显问题:
htt\ps多了多余的转义符,会导致匹配逻辑异常,正确写法应为https?- 仅判断前缀不是
]或)的逻辑太粗糙,会误排除普通文本中用括号包裹的裸URL,也可能误匹配到Markdown链接中的地址。
内容的提问来源于stack exchange,提问作者Boup
相关产品推荐
相关产品推荐

