Java中完美的URL验证正则表达式

Posted

技术标签:

【中文标题】Java中完美的URL验证正则表达式【英文标题】:Perfect URL validation regex in Java 【发布时间】:2015-10-05 02:31:14 【问题描述】:

我找到了该页面:https://mathiasbynens.be/demo/url-regex,其中很好地列出了用于 URL 验证的不同正则表达式及其可能性。 Diego Perini 的正则表达式是最强大的,我想在 Java 中使用它。但是,如果我这样使用它就行不通了:

public class URLValidation 
    // "\" replaced by "\\"
    private static Pattern REGEX = Pattern.compile("_^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d1,3)3)(?!127(?:\\.\\d1,3)3)(?!169\\.254(?:\\.\\d1,3)2)(?!192\\.168(?:\\.\\d1,3)2)(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d1,3)2)(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d1,2|2[0-4]\\d|25[0-5]))2(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x00a1-\\xffff0-9]+-?)*[a-z\\x00a1-\\xffff0-9]+)(?:\\.(?:[a-z\\x00a1-\\xffff0-9]+-?)*[a-z\\x00a1-\\xffff0-9]+)*(?:\\.(?:[a-z\\x00a1-\\xffff]2,)))(?::\\d2,5)?(?:/[^\\s]*)?$_iuS");

    private static String[] URLs = new String[]  "http://foo.com/blah_blah", "http://foo.com/blah_blah/", "http://foo.com/blah_blah_(wikipedia)", "http://foo.bar?q=Spaces should be encoded" ;

    public static void main(String[] args) throws Exception 
        for (String url : URLs) 
            Matcher matcher = REGEX.matcher(url);
            if (matcher.find()) 
                System.out.println(matcher.group());
            

此代码不输出任何内容,但它应该输出数组中的前三个 URL。如何正确编译正则表达式以使代码正常工作?

upd:感谢您的建议。我在实际应用程序中测试了您的正则表达式。我在那里做的是遍历日志文件并在每一行中查找 URL。日志文件的时间戳和用户名分别包含在 [] 和 中,有时可能包含负责格式化(颜色、粗体等)的特殊不可见字符,例如 \u0003。正则表达式似乎对那种类型的字符串有问题:http://ideone.com/WEcgBY

upd2:如果正则表达式包含多个 URL,那么如何查找一行中的所有 URL?例如像这样使用它:

String[] urlsFromLine = REGEX.split(line);
for (String url : urlsFromLine) 
    System.out.println(url);

【问题讨论】:

【参考方案1】:

使用这个版本:

"(?i)^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d1,3)3)(?!(?:169\\.254|192\\.168)(?:\\.\\d1,3)2)(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d1,3)2)(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d1,2|2[0-4]\\d|25[0-5]))2(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]2,))\\.?)(?::\\d2,5)?(?:[/?#]\\S*)?$"

您不必将斜杠加倍,在模式末尾添加正则表达式分隔符、修饰符,并将 \u 转换为 \x 表示法。

见IDEONE demo:

String[] URLs = new String[]  "http://foo.com/blah_blah", "http://foo.com/blah_blah/", "http://foo.com/blah_blah_(wikipedia)", "http://foo.bar?q=Spaces should be encoded" ;
Pattern REGEX = Pattern.compile("(?i)^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d1,3)3)(?!(?:169\\.254|192\\.168)(?:\\.\\d1,3)2)(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d1,3)2)(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d1,2|2[0-4]\\d|25[0-5]))2(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]2,))\\.?)(?::\\d2,5)?(?:[/?#]\\S*)?$");
for (String url : URLs) 
    Matcher matcher = REGEX.matcher(url);
    if (matcher.find()) 
       System.out.println(matcher.group());
    

输出:

http://foo.com/blah_blah
http://foo.com/blah_blah/
http://foo.com/blah_blah_(wikipedia)

更新

要匹配较大文本中的 URL,您需要将 ^$ 替换为 \\b

Pattern REGEX = Pattern.compile("(?i)\\b(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d1,3)3)(?!(?:169\\.254|192\\.168)(?:\\.\\d1,3)2)(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d1,3)2)(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d1,2|2[0-4]\\d|25[0-5]))2(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]2,))\\.?)(?::\\d2,5)?(?:[/?#]\\S*)?\\b");

见another demo

【讨论】:

这意味着您需要调整此正则表达式以匹配较大字符串中的 URL。您需要将^$ 替换为\\b,一个单词边界。 这是用占位符替换真实 URL 的 IDEONE。我会尝试一个单词边界。 我对你有下一个要求:) 不要使用split,在这种情况下它不起作用。 啊。但是我可以使用 "\\s" 拆分一个字符串,然后使用怪物正则表达式评估生成的字符串,对吗?

以上是关于Java中完美的URL验证正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 中的网站/URL 验证正则表达式

Java验证正则表达式

使用正则表达式在 JS 中验证 url [重复]

JavaScript 中正则表达式验证 URL 网址合法性,实用有效

URL 的 PHP 验证/正则表达式

使用正则表达式的 jQuery Youtube URL 验证