用正则表达式从字符串中提取出 URL
这可能是一个通用性的难题,能找到的方案也不尽善尽美,非 ASCII 字符集下就更复杂了,最后符合业务场景需求就行。
例子 🌰:u.jd.com/AnMpL4先领券!!https://u.jd.com/PSyXDO十斤70个橘子拍下9.9https://u.jd.com/J2VHdn
。
\bhttps?:\/\/[^,\s()<>]+(?:\([\w\d]+\)|(?:[^,[:punct:]\s]|\/))
0。
对非 ASCII 字符集非常不友好。
(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?
1。
此方案对带有协议的 URL 比较友好,分割成 协议、主机、其他(端口号、路径、参数等)三部分。
对于示例字符串,仅能匹配后两个 URL,不带协议的无法匹配出来。
\b((ftp|https?):\/\/)?([\w-\.]+\.(com|net|org|gov|mil|int|edu|info|me)|(\d+\.\d+\.\d+\.\d+))(:\d+)?(\/[\w-\/]*(\?\w*(=\w+)*[&\w-=]*)*(#[\w-]+)*)?
2。
跟 1 中的方案差不多,更进一步地把顶级域名单独摘出来了。
不用修改就可以完全匹配到示例中的三个字符串,其中最后一个匹配到的 URL 不带协议。
(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)
3。
✅ 完美匹配到三个 URL,不需要捕获分组可以简单修改为如下:
(?:https?:\/\/)?(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)
。
http[s]?:\/\/(?:(?!http[s]?:\/\/)[a-zA-Z]|[0-9]|[$\-_@.&+\/]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+
4。
仅能完全匹配到后两个 URL。
题外话:该页面标题处标示 内容来源于 Stack Overflow,并遵循 [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) 许可协议进行翻译与使用
, 然未发现任何链接指示原文出处。
References
- https://stackoverflow.com/a/5690614.
- https://stackoverflow.com/a/6041965.
- https://stackoverflow.com/a/58721703.
- https://digitalfortress.tech/tricks/top-15-commonly-used-regex/.
- https://cloud.tencent.com/developer/ask/219708/answer/337284.