我在一个Java测试套件中发现了以下问题
Pattern p = Pattern.compile("[wow]*");
Matcher m = p.matcher("wow its cool");
boolean b = false;
while (b = m.find()) {
System.out.print(m.start() + " \"" + m.group() + "\" ");
}
输出似乎如下
0 "wow" 3 "" 4 "" 5 "" 6 "" 7 "" 8 "" 9 "oo" 11 "" 12 ""
直到最后一场比赛很明显,模式[哇] *贪婪地匹配0或更多’w’和’o’字符,而对于不匹配的字符,包括空格,它会产生空字符串.然而,在将最后一个’l’与11“”匹配后,以下12“”似乎不清楚.在测试解决方案中没有详细说明,我也无法从javadoc中明确地解决这个问题.我最好的猜测是边界特征,但如果有人能提供解释,我将不胜感激
解决方法:
您看到此行为的原因是您的模式允许空匹配.换句话说,如果你传递一个空字符串,你会在零位置看到一个匹配:
Pattern p = Pattern.compile("[wow]*"); // One of the two 'w's is redundant, but the engine is OK with it
Matcher m = p.matcher(""); // Passing an empty string results in a valid match that is empty
boolean b = false;
while (b = m.find()) {
System.out.print(m.start() + " \"" + m.group() + "\" ");
}
这将打印0“”,因为空字符串与表达式的任何其他匹配一样好.
再回到你的例子,每当引擎发现一个匹配项(包括一个空的匹配项)时,它会通过一个字符前进. “前进一个”意味着引擎在下一个位置考虑弦的“尾部”.这包括正则表达式引擎处于位置11的时间,即最后一个字符的时间:这里,“尾部”由空字符串组成.这类似于调用“wow its cool”.substring(12):在这种情况下你也会得到一个空字符串.
引擎将空字符串视为有效输入,并尝试将其与表达式匹配,如上例所示.这会产生匹配,您的程序会正确报告.
标签:java,regex,string
来源: https://codeday.me/bug/20190528/1171866.html