从大量文本中提取数千个简单模式的快速算法
我希望能够从 GB 的文本中有效地匹配数千个正则表达式,因为我知道这些正则表达式中的大多数都相当简单,例如:
\bBarack\s(Hussein\s)?Obama\b \b(John|J\.)\sBoehner\b
等。
我当前的想法是尝试从每个正则表达式中提取某种最长的子字符串,然后使用 Aho-Corasick 匹配这些子字符串并消除大部分正则表达式,然后匹配所有剩余的正则表达式组合。有人能想出更好的办法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用 (f)lex 生成 DFA,它可以并行识别所有文字。如果存在太多通配符,这可能会变得棘手,但它适用于最多大约 100 个文字(对于 4 个字母的字母表;对于自然文本可能更多)。您可能想要抑制默认操作 (ECHO),并仅打印匹配的行号和列号。
[我假设 grep -F 的作用大致相同]
可以使用 awk 或任何其他脚本语言从 txt 输入生成类似上面的脚本。
You can use (f)lex to generate a DFA, which recognises all the literals in parallel. This might get tricky if there are too many wildcards present, but it works for upto about 100 literals (for a 4 letter alfabet; probably more for natural text). You may want to suppress the default action (ECHO), and only print the line+column numbers of the matches.
[ I assume grep -F does about the same ]
A script like the one above can be generated form txt input with awk or any other script language.
比在每个文件上运行每个正则表达式更聪明的实现:
但我不知道有任何程序已经执行此操作 - 您必须自己编写代码。这也意味着您有内存来保持正则表达式状态,并且您没有任何邪恶的正则表达式
A slightly smarter implementation than running every regex on every file:
But I don't know of any programs that do this already - you'd have to code it yourself. This also implies you have the ram to keep the regex state around, and that you don't have any evil regexes
我不确定你是否会打破一些正则表达式的大小限制,但你可以将它们全部组合成一个巨大的正则表达式:
如果你达到了某个限制,你可以一次使用 100 个块或任意数量的块来完成此操作可以管理
I'm not sure if you'd blow some regex size limit, but you could just OR them all up together into one giant regex:
If you hit some limit, you could do this with chunks of 100 at a time or however many you can manage
如果您需要快速实现某些特定情况,您可以实现 后缀树 “http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm” rel="nofollow">Aho–Corasick 算法 自己。但在大多数情况下,按照前面的建议,将所有正则表达式合并为单个正则表达式也不错
If you need really fast implementation of some specific case, you can implement suffix tree of Aho–Corasick algorithm yourself. But in most cases union of all your regexes into single regex, as recommended earlier, will be not bad too