Java正则表达式模式无法正常工作

时间:2016-04-30 12:53:16

标签: java regex

我是模式和正则表达式的新手,遇到了一个我无法解决的问题。 这是我的代码:

public static void main(String[] args) {

    Pattern pattern = Pattern.compile("(!?)(fw|ri|le|cl|rs)[\\s,]*(\\d*\\.*\\d*|\"\\w*\")?[\\s,]*(\\d*\\.*\\d*|\"\\w*\")?[\\s,]*(\\d*\\.*\\d*|\"\\w*\")?");
    Matcher matcher = pattern.matcher("!fw 90.0 \"hello\" 70.0");

    matcher.find();
    for(int i = 0; i < matcher.groupCount()+1; i++) {
        System.out.println("Group "+i+") " + matcher.group(i));
    }
}

所以,我已经使用regexr.com来创建正则表达式,并且在网站上它按计划运行。它应该找到3个参数,可以是数字或字符串,其中String用引号括起来。正如我所说,regexr.com 它可以工作,但是在java中它只有,当没有字符串时。我究竟做错了什么? (没有额外反斜杠的正则表达式是 (!?)(fw|ri|le|cl|rs)[\s,]*(\d*\.*\d*|"\w*")?[\s,]*(\d*\.*\d*|"\w*")?[\s,]*(\d*\.*\d*|"\w*")?

提前致谢。

编辑: 关于发生了什么以及不发生什么的一些例子:

按预期工作:

输入:!fw 1.0 2.0 3.0

输出: Group 0) !fw 1.0 2.0 3.0 Group 1) ! Group 2) fw Group 3) 1.0 Group 4) 2.0 Group 5) 3.0

未按预期工作:

输入:!fw 1.0 \"hello\" 3.0

输出: Group 0) !fw 1.0 Group 1) ! Group 2) fw Group 3) 1.0 Group 4) Group 5)

预期输出: Group 0) !fw 1.0 "hello" 3.0 Group 1) ! Group 2) fw Group 3) 1.0 Group 4) "hello" Group 5) 3.0

3 个答案:

答案 0 :(得分:1)

如果你改变字符串和数字的表达式顺序,你可以让你的正则表达式工作:

(!?)(fw|ri|le|cl|rs)[\\s,]*(\"\\w*\"|\\d*\\.*\\d*)?[\\s,]*(\"\\w*\"|\\d*\\.*\\d*)?[\\s,]*(\"\\w*\"\\d*\\.*\\d*)?

但是,我不确定你的正则表达式是否完全符合你的要求 - 它更具有匹配性,更具体。 E.g:

!fw ...""

这是因为你的正则表达式中有很多是可选的,或者可以重复多次。 (就像点,我猜测的不是你想要的。) 假设你想要正好有3组String或带有可选小数点的数字以及空格,逗号或没有分隔它们的数字,你应该使用这个正则表达式:

(!?)(fw|ri|le|cl|rs)([\\s,]*(\"\\w*\"|\\d+(\\.\\d+)?)[\\s,]*){3}

这将匹配Strings,例如:

!fw 90.0 \"hello\" 70.0

!fw \"hello\" 70.0

!fw\"hello\"70.0

但不匹配

!fw ...\"\"

这是因为在你的正则表达式中,你指定\\d*\\.*\\d*,这意味着&#34; 0-n数字,0-n点,0-n数字&#34;。通过将\\.*更改为\\.?,您可以指定&#34; 0-1点&#34;,这会解决您的点问题。但您仍然会将..9与此正则表达式匹配,这就是为什么您使用+使第一个数字成为强制性的,然后为小数点添加可选参数(\\.d+)? ,这意味着&#34; 1点和1-n数字&#34;。现在它将匹配没有小数点的数字和带小数点的数字,但不匹配3..3等数字。

{3}指定您希望该组恰好出现三次。如果您使用*保留这些组可选,那么您也可以获得0-2次出现模式的输入结果。如果这是您的预期行为,您应该考虑是否要在数字/字符串之间显示多个空格或逗号。如果不是,你应该让它们依赖于之前是否有字符串/数字。

答案 1 :(得分:1)

其中一种方法可能是将\\d*\\.更改为\\d+\\.。这样可以防止组接受空字符串,就像第4组和第5组一样(因为在检查|"\w*"部分之前可以接受这种情况)。

答案 2 :(得分:0)

我调试这样的问题的方法是简化你的非工作模式和String,如果有必要,直到它工作,然后再次开始构建它直到它中断。

在你的情况下,&#34;你好&#34; part是当前失败的地方,因此将字符串简化为:

"!fw 90.0 \"h"

所以你只有hello的开头并简化你的正则表达式:

(!?)(fw|ri|le|cl|rs)[\\s,]*(\\d*\\.*\\d*|\"\\w*\")?[\\s,]*(\"\\w)

所以它应该只匹配一个非可选的&#34;还有一封信。这对你的字符串很好。

然后我逐渐完成最后一部分

(\"\\w)

更像你的

(\\d*\\.*\\d*|\"\\w*\")

并重复直到它再次停止匹配。只要\\d*前面有|,就会发生这种情况。所以\ d *导致问题。为什么?正如Pshemo说的那样,因为它会尝试匹配0位或更多位数,甚至在尝试&#39;或&#39;之前的第二部分之前。因为它匹配0位数,所以正则表达式会成功,并且不会尝试你的\ w部分。

正如Pshemo提到的那样,将\ d *更改为\ d +修复了这个并且可能更符合您实际想要匹配的内容