我的 Java 11/Android 应用程序必须检查用户输入的 URL/IP 理论上是否有效(使用
myURL.trim().matches(regex)
)。
什么应该是有效的(包括变体):
什么不应该是有效的:
我不在乎用户是否输入,例如“999.999.999.999”,我只想知道语法在理论上是否正确,在这种情况下就是正确的。
到目前为止我一直在使用这个正则表达式:
String regex1 = "((http|https|ftp)://)?((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
...但现在我也想检查端口,^ 不支持。这个其他版本支持端口:
String regex2 = "((http|https|ftp)://)?(([^/:.[:space:]]+(.[^/:.[:space:]]+)*)|([0-9](.[0-9]{3})))(:[0-9]+)?((/[^?#[:space:]]+)([^#[:space:]]+)?(#.+)?)?";
...但对于“http://bla”或“---”等字符串,它会返回
true
。
我还测试了微软的这个版本:
String regex3 = "^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&%\\$#_]*)?$";
...但它不适用于上面的一些示例(“http://bla”和“http://10.1.1.9:1234/bla”是有效的,“10.1.1.9”和“stackoverflow. com”不是),我不知道如何让this长PHP版本与java一起工作,因为它抱怨“#”和“)”。
我知道 stackoverflow 上已经有很多用于验证 URL 的正则表达式代码,并且我已经测试了来自 mega-thread 的许多其他版本(以及其他问题),但是我可以让 Android Studio 来测试这些版本接受不起作用,我的正则表达式“知识”甚至不足以修改别人的代码,更不用说编写我自己的代码了。
我该如何实现这个目标?
我不想丢失这个正则表达式,以防将来需要它,所以我将它放在这里。
下面的正则表达式分为架构、子域、域、(c)TLD、IPv4 地址*、URL 路径、查询字符串和最终锚点的单独处理。
^(((ht|f)tps?)://)?(((\w+\-*\w+\.)*(\w+\-*\w+)(\.[\w]{2,})+)|(((1|2){0,1}[0-9]{1,2}\.){3}(1|2){0,1}[0-9]{1,2}))(:[0-9]{2,5})?(/(#/)?[\w0-9+\/\-]*(\?([\w0-9 ]+=([\w0-9]|%[0-7][0-9a-f])+&?)*)?(#[\w0-9]*)?)*$
它将把以下内容视为有效的 URL:
stackoverflow.com
http://stackoverflow.com
http://stack-overflow.com
http://test-1.stack-overflow.com/salsa1/#11223a
http://salsa.com/#/about-us
http://test.com/#/about--cats
http://amazon.co.uk
https://www.amazon.co.uk
ftp://10.1.1.9
10.1.1.9:1234/bla/bla/bla
255.1.1.9/bla/bla/bla
http://10.1.1.9:1234/bla/bla
http://amazon.co.uk/?name=value
http://amazon.co.uk/test?name=value&sasa=1
http://amazon10.com
它可能没有涵盖很多东西,但也许其他人可以编写更好的正则表达式。
* IP 地址仍然允许 299,但不允许 300 及以上。