匹配器只匹配第一个结果

Matcher only matches first result

现在我正在尝试学习如何使用匹配器、模式和所有这些东西,但我遇到了一个问题,我无法设法解决它,我确定我正在做一些事情错了,但我不知道是什么,所以我来这里寻求帮助,这是我的代码:

public static void main(String[] args) {
    Pattern pattern = Pattern.compile("effect:([^:]*)(?::([^:]*))?(\s)");
    Matcher matcher = pattern.matcher("effect:health:10 effect:speed:15 ");
    while (matcher.find()) {
        System.out.println(matcher.group(1));
        System.out.println(matcher.group(2));
    }
}

我想做的是从字符串中获取效果及其持续时间,但效果持续时间不是 100% 必需的,现在的问题是它只检测第一个效果,而不是第二个第一,它打印 'health' 和 '10',最后需要一个 space 否则它不起作用,但是如果我删除 '(\\s)' 它就不起作用。

英语不是我的母语,我尽力写了这篇文章,如果有任何拼写错误,我深表歉意。

我想你正在寻找类似的东西:

final Pattern pattern = Pattern.compile("effect:([^\s$:]+):?(\d*)");
final Matcher matcher = pattern.matcher("effect:health:10 effect:speed:15 effect:none:");
while (matcher.find()) {
    System.out.println(matcher.group(1) + ": [" + matcher.group(2) + "]");
}

输出:

health: [10]
speed: [15]
none: []

首先,由于您似乎并不关心捕获 space,请删除有关它的捕获组。

其次,由于 space 可能是可选的,所以添加一个 ?

现在,这会造成麻烦,因为 [^:] 会消耗 space,因此还要从捕获的值中排除 spaces。

实际上,通过这样做,您甚至不需要在最后匹配 space,所以完全删除它。

结果:

Pattern.compile("effect:([^:\s]*)(?::([^:\s]*))?")

查看 regex101 上的结果。


由于正则表达式 find() 将跳过 "bad" 数据,您可能需要添加额外的保护条件,例如如果输入是 "supereffect:a:b:c:d",你想匹配 return a/b 还是应该跳过它。

要跳过它,您可以添加保护条件,即匹配的模式必须:

  • 从 space 开始或之后开始:(?<=^|\s)
  • 在结尾或以 space 结束:(?=\s|$)
Pattern.compile("(?<=^|\s)effect:([^:\s]*)(?::([^:\s]*))?(?=\s|$)")