简化正则表达式 OR 模式

Posted

技术标签:

【中文标题】简化正则表达式 OR 模式【英文标题】:Simplifying regex OR patterns 【发布时间】:2011-04-16 20:33:07 【问题描述】:

今天有人问我是否有一个库来获取字符串列表并计算最有效的正则表达式以仅匹配这些字符串。我认为它本身就是一个NP Complete problem,但我认为我们可以稍微改进一下范围。

我将如何生成和简化一个正则表达式来匹配来自我网络上所有主机的更大集合的主机子集? (知道我可能得不到最有效的正则表达式。)

第一步很简单。来自以下列表;

appserver1.domain.tld appserver2.domain.tld appserver3.domain.tld

我可以将它们连接起来并转义到

appserver1\.domain\.tld|appserver2\.domain\.tld|appserver3\.domain\.tld

而且我知道如何手动将正则表达式简化为

appserver[123]\.domain\.tld

从那里我可以针对完整的主机列表测试该模式,并验证它是否仅与选定的 3 台主机匹配。我不知道如何自动化简化过程。是否有任何库(在 Perl、javascript 或 C# 中)或常见做法?

谢谢

更新我得到了一些很棒的 perl 模块,但我也喜欢前端解决方案。这意味着Javascript。我四处搜索,但没有人将 perl 模块移植到 JS,我没有成功找到搜索此类库的语言。

【问题讨论】:

【参考方案1】:

Regexp::Assemble::Compressed / Regexp::AssemblePreSuf 知道的技巧要多得多。 R::A 带有命令行工具assemble(默认未安装),这使得构建正则表达式更加容易。

【讨论】:

【参考方案2】:

Regex::PreSuf 模块正是为此而设计的。

引用概要:

use Regex::PreSuf;

my $re = presuf(qw(foobar fooxar foozap));

# $re should be now 'foo(?:zap|[bx]ar)'

【讨论】:

太棒了!我真的希望这也存在于 JS 中。【参考方案3】:

Perl 正则表达式编译器从模式中构建一个分支 trie 数据结构,其中的部分在备选方案中具有相同的部分:

 $ perl -Mre=debug -ce '"whatever" =~ /appserver1\.domain\.tld|appserver2\.domain\.tld|appserver3\.domain\.tld/'
Compiling REx "appserver1\.domain\.tld|appserver2\.domain\.tld|appserver3\."...
Final program:
   1: EXACT <appserver> (5)
   5: TRIEC-EXACT[123] (25)
      <1.domain.tld> 
      <2.domain.tld> 
      <3.domain.tld> 
  25: END (0)
anchored "appserver" at 0 (checking anchored) minlen 21 
-e syntax OK
Freeing REx: "appserver1\.domain\.tld|appserver2\.domain\.tld|appserver3\."...

【讨论】:

你能把编译好的正则表达式作为字符串拉出来吗?

以上是关于简化正则表达式 OR 模式的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法可以简化这个正则表达式?

Lua中的重复正则表达式

正则表达式简化 - 组太多

正则表达式中的重叠匹配

如何在 Hive 中使用正则表达式简化 g-mail 地址

简化 java 正则表达式代码以验证密码