【问题标题】:Matching several URLs in a string using regex使用正则表达式匹配字符串中的多个 URL
【发布时间】:2012-11-25 02:38:28
【问题描述】:

我正在尝试使用此处的正则表达式匹配字符串中的 URL:Regular expression to match URLs in Java

它适用于一个 URL,但是当我在字符串中有两个 URL 时,它只匹配后者。

代码如下:

Pattern pat = Pattern.compile(".*((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);
Matcher matcher = pat.matcher("asdasd http://www.asd.as/asd/123 or http://qwe.qw/qwe");
// now matcher.groupCount() == 2, not 4

编辑:我尝试过的东西:

// .* removed, now doesn't match anything // Another edit: actually works, see below
Pattern pat = Pattern.compile("((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);

// .* made lazy, still only matches one
Pattern pat = Pattern.compile(".*?((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])", Pattern.DOTALL);

有什么想法吗?

【问题讨论】:

    标签: java regex


    【解决方案1】:

    这是因为.* 是贪婪的。它会尽可能多地消耗(整个字符串)然后回溯。 IE。它会一次丢掉一个字符,直到剩下的字符可以组成一个 URL。因此,第一个 URL 将已匹配,但未捕获。不幸的是,比赛不能重叠。修复应该很简单。删除模式开头的.*。然后,您还可以从模式中删除外括号 - 无需再捕获任何内容,因为整个匹配项将是您要查找的 URL。

    Pattern pat = Pattern.compile("(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]", Pattern.DOTALL);
    Matcher matcher = pat.matcher("asdasd http://www.asd.as/asd/123 or http://qwe.qw/qwe");
    while (matcher.find()) {
      System.out.println(matcher.group());
    }
    

    顺便说一句,matcher.groupCount() 不会告诉您任何信息,因为它会为您提供模式中的组数,而不是目标字符串中的捕获数。这就是为什么您的第二种方法(使用.*?)没有帮助。您仍然有两个捕获组。在调用find 或其他任何东西之前,matcher 不知道它总共会找到多少捕获。

    【讨论】:

    • 删除 .* 没有帮助。抱歉,我稍后会添加我已经尝试过的东西。
    • @tsiki 您使用匹配器的方式可能与用于单个字符串中的多个匹配的方式不同。查看我的示例代码
    • 啊,谢谢,我的结果被弄脏了,因为我使用 if(matcher.matches()) { sysout(matcher.group(1) + matcher.group(2));) 打印它们.谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多