假设我有一个正则表达式列表(从外部源读取 - 文件,数据库等)。我想检查字符串匹配哪些正则表达式。
我可以通过所有这些正则表达式创建迭代并匹配它们,但列表可能很大,这是一个关键操作。
我可以将所有这些正则表达式合并为一个(在它们之间),但问题是我只能识别第一个匹配的正则表达式,而不是全部。
另一个想法可能是为所有这些正则表达式创建一个自动机,并用相应正则表达式的索引标记最终状态。我正在查看http://cs.au.dk/~amoeller/automaton/,这个库似乎能够使用正则表达式和自动机,但不确定它是否可以扩展以解决我的问题。
你还有其他想法吗?
为了澄清一些评论,我添加了一个代码示例:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PatternTest {
public static void main(String[] args) {
Pattern p = Pattern.compile("(a(?:b|c)a)|((?:a|b)ba)|(ab(?:a|c))");
Matcher m = p.matcher("aba");
System.out.println(m.matches());
System.out.println(m.groupCount());
for (int i = 0, n = m.groupCount(); i < n; i++) {
System.out.println(m.group(i));
}
}
}
将打印出来
true
3
aba
aba
null
正如您所看到的那样,只有第一组匹配,而我找不到匹配其他两组的方法。
更多调查结果 - 使用上面的自动机库,问题将减少到以下几点:如果连接两个或多个自动机,如何识别哪个原始自动机对应的最终状态?
答案 0 :(得分:5)
我实现了基于dk.brics.automaton的解决方案,你可以在这里找到它。 https://github.com/fulmicoton/multiregexp
答案 1 :(得分:3)
对于确定的答案(如果有的话),我们需要更多信息,例如:
你说正则表达的列表是巨大的;你可以说得更详细点吗?成千上万的?百万?数十亿甚至数十亿?
谁写了这些正则表达式,他们知道他们在做什么吗?在将正则表达式添加到列表之前是否已经过彻底测试(正确性和性能)?
在示例代码中,您使用matches()
方法,该方法需要正则表达式来描述整个字符串。就像正则表达式真的一样
\A(?:(a(?:b|c)a)|((?:a|b)ba)|(ab(?:a|c)))\z
匹配"aba"
但不匹配"aaba"
或"abaa"
。如果您在使用Java之前已在其他工具或语言中使用了正则表达式,则此行为可能会让您感到惊讶。传统上,如果正则表达式描述字符串中的任何子串,甚至是零长度子字符串,则字符串总是被称为“匹配”正则表达式。要在Java中获得该行为,您必须使用Matcher的find()
方法。
是否有任何常见因素可以从列表中的所有正则表达式中提取出来,例如最小或最大长度,公共子串或共享字符子集?例如,与您的某个示例模式匹配的任何字符串也必须与[abc]{3}
匹配。如果有,你可能想要在严重匹配开始之前运行基于它们的过滤器(可能是正则表达式,也许不是)。 (如果您使用的是Perl,我不会建议这样做,这是一个已经优化过的choc-a-bloc,但是Java并不自豪地接受一点帮助.☺)
但是我觉得很安全,建议你使用单独的正则表达式,而不是将它们连成一个。 Frankenregex不一定表现更好,故障排除将是一场噩梦!您可以预编译所有Pattern对象,并且可以提前创建Matcher对象并将其重用于所有匹配项,如下所示:
m.reset(s).usePattern(p);
这是一个demo。我无法做出任何保证(一方面,你仍然受到编写正则表达式的人的支配),但如果解决方案成为可能,我认为这是最有希望的方法。
答案 2 :(得分:2)
dk.brics.automaton并不直接支持这一点,但您可以概括自动机(以及相关的自动机操作)的表示来区分不同类型的接受状态。首先,将一个int字段添加到State类,并在“接受”时使用此字段。已经确定了。