我的 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.html”)。 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 及以上。
通过一项增强功能将我的评论转换为答案。您可以使用这个优化正则表达式:
^(?:(?:ht|f)tps?://)?(?=(?:\d{1,4}(?:\.\d{1,4}){3}|[^:/\n]*[^:/.\d\n])(?:[:/]|$))[\da-z](?!\w*-[/.?])[\w-]*(?:\.[-\w]*[\da-z])+(?::\d+)?(?:/[-\w.?\,'/\\\+&;%\$#?&=]*)?$
这可能是用于检查 URL 是否有效的最完整的正则表达式
^(((ht|f)(tp)(s)?(:\/\/))?(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))(:\d{1,5})?((\/)([\w\.~%-]+))*(\/)?((\?)(([\w]+)(=[\w\.~%-])?((&)([\w]+)(=[\w\.~%-])?)*)?)?((#)((([\w]+(=[\w\,\*\.~%-]+)?)(&[\w]+(=[\w\,\*\.~%-]+)?)*)|(:~:text=([\w\.~%-]+\,)?([\w\.~%-]+)(\,[\w\.~%-]+){0,2}))?)?)$
第一部分:方案
- http://
- https://
- ftp://
- ftp://
((ht|f)(tp)(s)?(:\/\/))?
第二部分:域名或 IPv4 地址
- 192.168.0.1
- stackoverflow.com
(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))
第三部分:端口
- :65535
- :1
(:\d{1,5})?
第四部分:路径
- /教育/
- /关于
- /acc/用户/管理
((\/)([\w\.~%-]+))*(\/)?
第五部分:查询
- ?查询=a&b=c
((\?)(([\w]+)(=[\w\.~%-]+)?((&)([\w]+)(=[\w\.~%-]+)?)*)?)?
第六部分:碎片
- #关于
- #行=10,20
- #行=5-7
- #行=5-*
- #细胞=4,1-6,2
- #t=40,80&xywh=160,120,320,240
- #:~:text=前缀-,textStart,textEnd,-后缀
^(((ht|f)(tp)(s)?(:\/\/))?(([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))(:\d{1,5})?((\/)([\w\.~%-]+))*(\/)?((\?)(([\w]+)(=[\w\.~%-]+)?((&)([\w]+)(=[\w\.~%-]+)?)*)?)?((#)((([\w]+(=[\w\,\*\.~%-]+)?)(&[\w]+(=[\w\,\*\.~%-]+)?)*)|(:~:text=([\w\.~%-]+\,)?([\w\.~%-]+)(\,[\w\.~%-]+){0,2}))?)?)$
作为参考,这里是相关的 ABNF,来自 RFC 1738 – 统一资源定位器 (URL)。
genericurl = scheme ":" schemepart
scheme = 1*[ lowalpha | digit | "+" | "-" | "." ]
schemepart = *xchar | ip-schemepart
ip-schemepart = "//" login [ "/" urlpath ]
login = [ user [ ":" password ] "@" ] hostport
user = *[ uchar | ";" | "?" | "&" | "=" ]
password = *[ uchar | ";" | "?" | "&" | "=" ]
hostport = host [ ":" port ]
host = hostname | hostnumber
hostname = *[ domainlabel "." ] toplabel
hostnumber = digits "." digits "." digits "." digits
domainlabel = alphadigit | alphadigit *[ alphadigit | "-" ]
toplabel = alpha | alpha *[ alphadigit | "-" ] alphadigit
port = digits
urlpath = *xchar ; depends on protocol see section 3.1
uchar = unreserved | escape
xchar = unreserved | reserved | escape
unreserved = alpha | digit | safe | extra
safe = "$" | "-" | "_" | "." | "+"
extra = "!" | "*" | "'" | "(" | ")" | ","
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "="
escape = "%" hex hex