Java:如何确定正则表达式模式匹配失败的原因?

时间:2011-04-18 19:51:21

标签: java regex

我使用正则表达式来匹配模式是否匹配,但我也想知道它何时失败。

例如,假设我有一个“N {1,3} Y”的模式。我将它与字符串“NNNNY”匹配。我想知道它失败了因为Ns太多了。或者如果我将它与字符串“XNNY”匹配,我想知道它失败了,因为字符串中包含无效字符“X”。

通过查看Java正则表达式包API(java.util.regex),匹配成功时,似乎只能从Matcher类中获取其他信息。

有没有办法解决这个问题?或者在这种情况下,正则表达式是一个选项吗?

4 个答案:

答案 0 :(得分:9)

我想你应该使用解析器,而不是简单的正则表达式。

正则表达式可以很好地为字符串提供匹配,但在提供非匹配时并不完全相同,更不用说解释匹配失败的原因了。

答案 1 :(得分:2)

它可能有效,但我不知道你是否需要它。

使用matches时,如果整个序列不匹配,则会失败,但您仍然可以使用find查看序列的其余部分是否包含模式,从而了解失败的原因:

import java.util.regex.*;
import static java.lang.System.out;
class F { 
    public static void main( String ... args ) { 
        String input = args[0];
        String re = "N{1,3}Y";
        Pattern p = Pattern.compile(re);
        Matcher m = p.matcher(input);
        out.printf("Evaluating: %s on %s%nMatched: %s%n", re, input, m.matches() );
        for( int i = 0 ; i < input.length() ; i++ ) { 
           out.println();
           boolean found = m.find(i);
           if( !found ) { 
               continue;
           }
           int s = m.start();
           int e = m.end();
           i = s;
           out.printf("m.start[%s]%n"
                     +"m.end[%s]%n"
                     +"%s[%s]%s%n",s,e,
                     input.substring(0,s), 
                     input.substring(s,e), 
                     input.substring(e) );
        }

    }
}

输出:

C:\Users\oreyes\java\re>java F NNNNY
Evaluating: N{1,3}Y on NNNNY
Matched: false

m.start[1]
m.end[5]
N[NNNY]

m.start[2]
m.end[5]
NN[NNY]

m.start[3]
m.end[5]
NNN[NY]


C:\Users\oreyes\java\re>java F XNNY
Evaluating: N{1,3}Y on XNNY
Matched: false

m.start[1]
m.end[4]
X[NNY]

m.start[2]
m.end[4]
XN[NY]

在第一个输出中:N[NNNY]你可以告诉那里有太多的N,在第二个输出中:X[NNY]有一个X存在。

这是其他输出

C:\Users\oreyes\java\re>java F NYXNNXNNNNYX
Evaluating: N{1,3}Y on NYXNNXNNNNYX
Matched: false

m.start[0]
m.end[2]
[NY]XNNXNNNNYX

m.start[7]
m.end[11]
NYXNNXN[NNNY]X

m.start[8]
m.end[11]
NYXNNXNN[NNY]X

m.start[9]
m.end[11]
NYXNNXNNN[NY]X

模式存在,但整个表达不匹配。

有点难以理解查找,匹配和查找是如何从文档中工作的(至少这发生在我身上)但我希望这个例子可以帮助你解决这个问题。

匹配就像/^YOURPATTERNHERE$/

lookingAt就像/^YOURPATTERNHERE/

find就像/YOURPATTERNHERE/

我希望这会有所帮助。

答案 2 :(得分:1)

您要求的是解析器确定附近的字符串,该字符串实际上与您的表达式匹配。这是一个非常重要的问题,可能会在指数时间内运行(例如,搜索所有可能的相似长度的字符串以找到匹配项。)

所以,简而言之,没有。

答案 3 :(得分:0)

对于像“N {1,3} Y”这样的简单表达式,您将自己找到没有工具的解决方案。但对于更复杂的表达方式,我的经验表明:

  • 将较大的表达式拆分为较小的表达式,并独立测试它们。
  • 因为你喜欢快速反馈,你可以使用像Beanshell这样的交互式shell来快速测试一些字符串和模式,无需大量编译,public static void main(bla ...)等等。或者尝试使用scala完成此任务。 Sed是另一种使用正则表达式的强大工具,但语法上存在细微差别,这可能会引入新的错误。
  • 通常,掩蔽是一个问题。由于反斜杠需要另一个反斜杠,因此从JTextField读取表达式可能是一个优势,在那里您不需要那么多的屏蔽。
  • 为您的表达式编写一个小型测试框架,您可以轻松地将表达式放入测试字符串中,也可以生成自动测试数据,并获得视觉反馈。