我是模式和正则表达式的新手,遇到了一个我无法解决的问题。 这是我的代码:
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
答案 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 +修复了这个并且可能更符合您实际想要匹配的内容