如何与java.util.regex执行部分匹配。*?

我一直在使用Java中的正则表达式java.util.regex。*类,到目前为止一切都很好。 但今天我有不同的要求。 例如,将模式视为“aabb”。 现在,如果输入字符串是aa肯定不匹配,但是如果我追加bb它仍然有可能变成aabb并且它匹配。 但是,如果我开始使用cc,无论我追加什么,它都永远不会匹配。

我已经探索了Pattern和Matcher类,但没有找到任何方法来实现这一点。

输入将来自用户,系统必须等到模式匹配,否则它将永远不会与任何输入进行匹配。

任何线索?

谢谢。

您应该更仔细地查看Matcher API; hitEnd()方法完全按照您的描述工作:

 import java.util.regex.*; public class Test { public static void main(String[] args) throws Exception { String[] ss = { "aabb", "aa", "cc", "aac" }; Pattern p = Pattern.compile("aabb"); Matcher m = p.matcher(""); for (String s : ss) { m.reset(s); if (m.matches()) { System.out.printf("%-4s : match%n", s); } else if (m.hitEnd()) { System.out.printf("%-4s : partial match%n", s); } else { System.out.printf("%-4s : no match%n", s); } } } } 

输出:

 aabb : match aa : partial match cc : no match aac : no match 

据我所知,Java是唯一公开此function的语言。 还有requireEnd()方法,它告诉你更多输入是否可以将匹配变为不匹配,但我不认为它与你的情况相关。

添加了这两种方法以支持Scanner类,因此它可以将正则表达式应用于流,而无需将整个流读入内存。

 Pattern p = Pattern.compile(expr); Matcher m = p.matcher(string); m.find(); 

所以你想知道String是否与正则表达式匹配,但是是否可能有更长的String以匹配的s开头? 抱歉,Regexes无法帮助您,因为您无法访问匹配器的内部状态; 你只得到布尔结果和你定义的任何组,所以你永远不知道匹配失败的原因。

如果您愿意破解JDK库,则可以扩展(或可能派生) java.util.regex并提供有关匹配过程的更多信息。 如果匹配失败,因为输入“用完”,答案就是真的 ; 如果由于性格歧视或其他检查而失败,那将是错误的 。 这似乎是很多工作,因为你的问题完全与正则表达式应该做的相反。

另一个选择:也许您可以简单地重新定义任务,以便您可以将输入视为正则表达式并将aabb与* aa。**匹配? 但是,你必须要小心正则表达式元字符。

对于您给出的示例,您可以尝试使用反模式来取消无效结果的资格。 例如,“^ [^ a]”会告诉您输入“c …”与“aabb”的示例模式不匹配。

根据您的模式,您可以将其分解为更小的模式以检查和使用多个匹配器,然后在发生一个匹配时设置其边界,然后移动到下一个匹配。 这种方法可能有效,但是如果你的模式很复杂并且可以有可变长度的子部分,你最终可能会在你自己的代码中重新实现匹配器的一部分,以调整匹配的可能范围,使其或多或少贪婪。 伪代码的一般概念是:

 boolean match(String input, Matcher[] subpatterns, int matchStart, int matchEnd){ matcher = next matcher in list; int stop = matchend; while(true){ if matcher.matches input from matchstart -> matchend{ if match(input, subpatterns, end of current match, end of string){ return true; }else{ //make this match less greedy stop--; } }else{ //no match return false; } } } 

然后,您可以将此想法与反模式合并,并具有反子模式,并在每个子模式匹配后检查下一个反模式,如果匹配,则表示您已失败,否则继续匹配模式。 您可能希望返回类似枚举而不是布尔值的东西(即ALL_MATCHED,PARTIAL_MATCH,ANTI_PATTERN_MATCH,……)

再次取决于您尝试匹配的实际模式的复杂性,相应的子模式/反模式可能很难,如果不是不可能的话。

一种方法是将正则表达式解析为一系列子正则表达式,然后以允许您进行部分匹配的方式重新组合它们; 例如,“ab c”有3个子正则表达式“a”,“b ”和“c”,然后你可以将它们重组为“a(b *(c)?)?”。

当输入正则表达式包含交替和组时,事情变得更复杂,但是相同的一般方法应该起作用。

这种方法的问题在于,由此产生的正则表达式更复杂,并且可能导致复杂输入正则表达式的过度回溯。

如果你使正则表达式的每个字符都是可选的并放宽多重约束,那么你就得到了你想要的东西。 例如,如果你有一个匹配的模式“aa(abc)+ bbbb”,你可以有一个’可能的匹配’模式’a?a?(a?b?c?)* b?b?b?b?’。

这种产生可能匹配模式的机械方式虽然不包括前向和后向参考等高级结构。

您可以使用状态机( http://en.wikipedia.org/wiki/State_machine )完成此任务。 让状态/转换表示有效输入和一个错误状态。 然后,您可以一次向状态机提供一个字符(可能是子字符串,具体取决于您的数据)。 您可以随时检查状态机是否处于错误状态。 如果它不处于错误状态,那么您知道未来的输入可能仍然匹配。 如果它处于错误状态,那么您知道以前失败的东西,任何将来的输入都不会使字符串有效。