java - 使用正则表达式匹配字符串中的多个 URL

标签 java regex

我正在尝试使用此处的正则表达式来匹配字符串中的 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);

有什么想法吗?

最佳答案

这是因为.*是贪婪的。它只会消耗尽可能多的内容(整个字符串),然后回溯。 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 并不知道它总共会找到多少个捕获。

关于java - 使用正则表达式匹配字符串中的多个 URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13754255/

相关文章:

c# - C# 中的正则表达式提取子字符串

java - 在节点中查找关键字并获取 DOM 中的节点名称

python - 如何在Python中使用re替换和小写2个或更多组

java - 如何检查类中所有字段的空性和 null 并实现用户定义的异常?

Java - 不能从静态上下文中引用

java - MyBatis 中嵌套的 <collection> 和 <association> 给出 NULL 作为结果

java - 如何使用 HQL 查询连接 hibernate Value 对象?

java - 这段代码无法编译,问题是什么(Java)

c++ - 括号和新行的 Qt/QRegExp 正则表达式或 "\r"?

regex - perl正则表达式查找模式只在文本的前面