正则表达式发生器/减速器?

时间:2010-07-07 15:05:59

标签: regex algorithm

我向同事提出了一个有趣的问题,我们目前有一个操作上的痛点,如果那里有任何东西(实用程序/库/算法)可能有助于自动化,我很感兴趣。

假设您有一个文字值列表(在我们的例子中,它们是URL)。我们想要做的是,根据这个列表,提出一个匹配所有这些文字项的正则表达式。

所以,如果我的清单是:

http://www.example.com
http://www.example.com/subdir
http://foo.example.com

最简单的答案是

^(http://www.example.com|http://www.example.com/subdir|http://foo.example.com)$

但是这对于大量数据而言变得很大,而且我们有一个长度限制,我们试图保持不变。

目前我们手动编写正则表达式,但这不能很好地扩展,也不是任何人的时间。是否有更自动化的方法来分解源数据,以提供与所有源值匹配的长度最佳正则表达式?

8 个答案:

答案 0 :(得分:15)

Aho-Corasick匹配算法构造有限自动机以匹配多个字符串。您可以将自动机转换为等效的正则表达式,但直接使用自动机更简单(这就是算法所做的。)

答案 1 :(得分:8)

可以使用正则表达式的自动生成器here。该工具具有Web界面,并使用Genetic Programming从一组示例生成正则表达式:您可以选择为Java或JavaScript正则表达式引擎准备的语法。它由我们的研究小组开发,并已在GECCO 2012会议上发表。

答案 2 :(得分:6)

今天我在搜索。我没找到它,所以我创建了一个工具:kemio.com.ar/tools/lst-trie-re.php

你在右侧放置一个列表,提交它,然后在左侧获得正则表达式。

我尝试了一个6Kb的单词列表,并产生了一个4Kb的正则表达式(我把它放在JS文件中),如:var re=new RegExp(/..../,"mib");

请不要滥用它。

答案 3 :(得分:3)

Emacs实用程序函数regexp-optsource code)并不能完全符合您的要求(它仅适用于固定字符串),但它可能是一个有用的起点。

答案 4 :(得分:2)

如果您想要与一组中的所有字符串进行比较,并且仅针对这些字符串进行比较,请使用triecompressed trie,或更好的directed acyclic word graph。对于URL IMO,后者应该特别有效。

你必须放弃正则表达式。

答案 5 :(得分:1)

我认为退一步思考你正在做什么以及为什么这样做是有意义的。

要匹配所有这些网址,只匹配那些网址而不是其他网址,您不需要正则表达式;通过对URL列表中的每个项目进行精确的字符串比较,您可以获得可接受的性能。

如果你确实需要正则表达式,那么你试图容纳的变量差异是什么?即输入的哪一部分必须逐字匹配,哪里有摆动空间?

如果你确实想要使用正则表达式来匹配固定的字符串列表,可能是出于性能原因,那么编写一个将所有输入字符串粘合在一起作为替代方法的方法应该很简单,就像在你的例子中一样。在幕后进行正则表达式匹配的状态机非常聪明,如果您的匹配备选方案具有共同(因而可能是冗余的)子串,则运行速度不会更慢。

答案 6 :(得分:1)

从另外两个答案中得到提示,你需要匹配的只是提供的字符串,你最好做一个直接的字符串匹配(慢)或构建一个匹配这些字符串的快速FSM(快速)。 / p>

正则表达式实际上会创建一个FSM,然后将输入与它匹配,因此如果输入来自一组先前已知的集合,则可能并且通常更容易自己制作FSM而不是尝试自动生成正则表达式

Aho-Corasick已被建议。它很快,但实施起来可能很棘手。如何将所有字符串放在Trie中然后查询(因为您匹配整个字符串,而不是搜索子字符串)?

答案 7 :(得分:0)

一种简单的方法是使用Python的hachoir_regex模块:

urls = ['http://www.example.com','http://www.example.com/subdir','http://foo.example.com']
as_regex = [hachoir_regex.parse(url) for url in urls]
reduce(lambda x, y: x | y, as_regex)

创建简化的正则表达式

http://(www.example.com(|/subdir)|foo.example.com)

代码首先为每个URL创建一个简单的正则表达式类型,然后在reduce步骤中将它们与|连接起来。