生成正则表达式以匹配列表A中的字符串,但不匹配列表B中的字符串

时间:2012-10-14 22:13:38

标签: java regex string algorithm text

  

可能重复:
  How to auto generate regex from given list of strings?

我有两个字符串 ListA ListB 列表。我需要生成一个匹配 ListA 中所有字符串的正则表达式,并且不匹配 ListB 中的任何字符串。

  • 字符串可以包含字符,数字和标点符号的任意组合。
  • 如果字符串出现在 ListA 上,则可以保证它不会出现在 ListB 中。
  • 如果字符串不在这两个列表中的任何一个中,我不关心匹配的结果应该是什么。

列表通常包含数千个字符串,字符串彼此非常相似。

我知道这个问题的简单答案,它只是生成(Str1)|(Str2)|(Str3)形式的正则表达式,其中StrN是ListA中的字符串。但我正在寻找一种更有效的方法来实现这一目标。

理想的解决方案是某种工具,它将采用两个列表并为此生成Java正则表达式。

更新1 :通过“高效”,我的意思是生成比简单解决方案更短的表达式。理想的算法会产生短路表达。以下是一些例子。

ListA = { C10 , C15, C195 }
ListB = { Bob, Billy }

理想的表达方式是

/^C1.+$/

另一个例子,请注意ListB的第三个元素

ListA = { C10 , C15, C195 }
ListB = { Bob, Billy, C25 }

理想的表达方式是

/^C[^2]{1}.+$/

最后一个例子

ListA = {A,D,E,F,H}    ListB = {B,C,G,I}

理想表达式与

的简单解决方案相同
/^(A|D|E|F|H)$/

另外,我不是在寻找理想的解决方案,任何比琐碎更好的方法都会有所帮助。我正在考虑生成简单解决方案列表,然后尝试合并公共子串,同时观察我们不会漫游到ListB区域。

**更新2 *:我并不特别担心生成RegEx所需的时间,现代机器上10分钟以下的任何东西都可以接受

1 个答案:

答案 0 :(得分:1)

如果确保两个列表中都没有字符串,并且您不关心两个列表中的字符串,那么您只需匹配ListA中的字符串;你可以完全忽略ListB。

您提到的“琐碎答案”是一个完全合理的解决方案。当你说你想要一种“更有效”的方式时,你是指一种生成正则表达式本身的有效方法,还是一种生成更有效匹配字符串的正则表达式的方法?

  • 如果要有效地生成正则表达式,大多数语言的字符串工具提供了一种方法来使用分隔符字符串(例如逗号)来连接字符串列表以生成单个字符串。你无法真正提高效率。
  • 如果您希望表达式有效地匹配事物,请确保在使用它之前“编译”它。 (大多数正则表达式库都有此功能。)编译正则表达式意味着生成正则表达式库实际用于匹配操作的finite-state machine。任何体面的正则表达式库都应该在优化FSM方面做得不错,例如在可能的情况下将公共子串映射到相同的FSM状态。

或者,您可以完全放弃正则表达式,只需迭代ListA并将其每个字符串与候选字符串进行比较。在这种情况下,单独比较可能更快,因为查找精确的字符串匹配可以比较4或8字节块中的字符串,而正则表达式必须单独查看每个字符。但是如果你有很多要比较的字符串,你将在内存中多次遍历候选字符串。相反,正则表达式可以遍历候选字符串一次以查明它是否匹配。

尝试两种方法。看哪个更快。