用于URL验证的正则表达式,包含部分捕获

4

一个正则表达式能否用于验证URL并匹配所有部分?我一直在研究一个,到目前为止我想到的是:

(?:(?P<scheme>[a-z]*?)://)?(?:(?P<username>.*?):?(?P<password>.*?)?@)?(?P<hostname>.*?)/(?:(?:(?P<path>.*?)\?)?(?P<file>.*?\.[a-z]{1,6})?(?:(?:(?P<query>.*?)#?)?(?P<fragment>.*?)?)?)?

然而,这并不起作用,它应该匹配以下所有示例:

http://username:password@hostname.tld/path?arg=value#anchor
http://www.domain.com/
http://www.doamin.co.uk/
http://www.yahoo.com/
http://www.google.au/
https://username:password@domain.com/
ftp://user:password@domain.com/path/
https://www.blah1.subdoamin.doamin.tld/
domain.tld/#anchor
doamin.tld/?query=123
domain.co.uk/
domain.tld
http://www.domain.tld/index.php?var1=blah
http://www.domain.tld/path/to/index.ext
mailto://user@unkwndesign.com

这是一段包含各种链接的HTML代码,链接内容包括用户名、密码、主机名、路径、查询参数和锚点等。其中有http、https、ftp和mailto等不同协议的链接。
并为所有组件提供命名捕获:

协议,例如http,https,ftp,ftps,callto,mailto和任何未列出的协议
用户名
密码
主机名包括子域,域和顶级域
路径,例如/images/profile/
文件名,例如file.ext
查询字符串,例如?foo=bar&bar=foo
片段,例如#anchor

其中主机名是唯一必填字段。

我们可以假设这来自一个专门要求URL的表单,并且不会用于在文本中查找链接。


假设还有一个 PCRE 库。 - UnkwnTech
这个链接类似但不完全符合需求,它没有包含名称捕获和用户名:密码。 - UnkwnTech
我建议您如果需要安全和完美的话,最好不要使用正则表达式。 - Pacerier
2个回答

12

能否使用单个正则表达式验证url并匹配所有部分?

不能。

Strager的正则表达式令人印象深刻,但归根结底,与使用适当的URI解析器相比,它的可读性、可维护性和可靠性较低。这种正则表达式必然会拒绝有效的URI,并接受不是URI的字符串,因为URI格式的规则无法完全用正则表达式表示。

mailto:// user@unkwndesign.com

在mailto URI中不应该有“//”。在读取方案之前,您无法确定URI的其余部分(冒号后面)的格式;许多URI方案不符合credentials@host/path格式。最好只接受您知道如何解析其URI的特定方案。


6

修改版的mingfai的正则表达式:

/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

它具有非贪婪匹配,因此可以接受无效输入:即在非贪婪匹配位置处的额外无意义内容。 - Eamon Nerbonne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接