假设我有一个正则表达式列表(从外部源读取 - 文件,数据库等)。我想检查字符串匹配哪些正则表达式。
我可以通过所有这些正则表达式创建迭代并匹配它们,但列表可能是一个巨大的,这是一个关键的操作。
我可以将所有这些正则表达式合并为一个(在它们之间),但问题是我只能识别第一个匹配的正则表达式,而不是全部。
另一个想法可能是为所有这些正则表达式创建一个自动机,并用相应正则表达式的索引标记最终状态。我在看 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
正如您所看到的,只有第一组匹配,我没有找到匹配其他两组的方法。
更多发现 - 使用上面的自动机库,问题将减少到以下几点:如果连接两个或多个自动机,如何识别哪个原始自动机对应的最终状态?
dk.brics.automaton 并不直接支持这一点,但您可以概括自动机(以及相关的自动机操作)的表示来区分不同类型的接受状态。首先,将一个int字段添加到 州 class并在设置'accept'时使用此字段。
我实现了基于dk.brics.automaton的解决方案,你可以在这里找到它。
https://github.com/fulmicoton/multiregexp
对于确定的答案(如果有的话),我们需要更多信息,例如:
你说正则表的列表是巨大的;你可以说得更详细点吗?成千上万的?百万?数十亿甚至数十亿?
谁写了这些正则表达式,他们知道他们在做什么吗?是否正确测试了正则表达式(正确性 和 性能)在被添加到列表之前?
在您的示例代码中,您使用了 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);
这是一个 演示。我无法做出任何保证(一方面,你仍然受到编写正则表达式的人的支配),但如果解决方案成为可能,我认为这是最有希望的方法。