Regex 哪个正则表达式性能更好?

Regex 哪个正则表达式性能更好?,regex,Regex,我想用一个通用前缀(/files)来匹配URL,但在它下面只有两个特定的目录——图像和视频。我可以为此想出两个正则表达式: ^/files/(?:image|video)s/ /files/(图像/*|视频/*) 及 /files/(image | video)s/* 我这里有两个问题: 从性能角度看,哪一个更好?我的猜测是第二个,因为它的DFA将拥有较少的州 是否有一种通用编程语言,其内置的正则表达式编译器会将给定的正则表达式简化为最小的DFA 性能对我很重要,因为我将使用它来匹配数十亿个字

我想用一个通用前缀(/files)来匹配URL,但在它下面只有两个特定的目录——图像和视频。我可以为此想出两个正则表达式:

^/files/(?:image|video)s/
/files/(图像/*|视频/*)

/files/(image | video)s/*

我这里有两个问题:

  • 从性能角度看,哪一个更好?我的猜测是第二个,因为它的DFA将拥有较少的州
  • 是否有一种通用编程语言,其内置的正则表达式编译器会将给定的正则表达式简化为最小的DFA
  • 性能对我很重要,因为我将使用它来匹配数十亿个字符串。因此,任何微小的改进对我来说都很重要。

    Python 2.7说:

    import timeit
    once = 'import re; m="/files/images/test"'
    num = 1000000
    print timeit.timeit(stmt='re.findall(r"/files/(images/.*|videos/.*)", m)', setup=once, number=num)
    -> 1.5884420871734619
    print timeit.timeit(stmt='re.findall(r"/files/(image|video)s/.*", m)', setup=once, number=num)
    -> 1.5990869998931885
    
    这将使用regex 100万次,并且在运行两条线多次后,两条线的速度都相同

    Python可能会缓存已编译的正则表达式

    我试了一下

    • /文件/图像/测试
    • /文件/视频/测试
    • /文件/视频/测试
    你的第一个版本(
    /files/(images/*| videos/*)
    )在我的测试中运行快了一点(0.1秒)

    我的直觉(我知道不是太有用)会说第二个选项更好。但是考虑一下:

    • 为什么要添加
      *
    • 能否将正则表达式锚定到行的开头
    • 你需要捕获该组吗
    如果这些都适用,我会这样做:

    ^/files/(?:image|video)s/
    
    从性能角度看,哪一个更好?我的猜测是第二个,因为它的DFA将拥有较少的州

    这两个表达式在最小DFA中具有相同数量的状态,并且它们的DFA匹配相同的“语言”(理论意义上)

    无论DFA中的状态数是多少,性能在理论上都是相同的,因为在将输入提供给自动机时,您将确定地遍历这些状态

    在实践中,由于缓存未命中,可能会有差异,当存在更多状态时,这种情况可能会更频繁地发生。然而,除非你在使用正则表达式引擎,否则我想不出有什么好的理由花时间进行黑盒优化

    是否有一种通用编程语言,其内置的正则表达式编译器会将给定的正则表达式简化为最小的DFA

    Go()和Haskell拥有将regex转换为DFA的引擎。不过,我不知道DFA是否最小

    由于POSIX ERE不支持反向引用(反向引用与替换中捕获组的引用不同),因此可以为POSIX ERE编写一个在DFA或高效NFA模拟上运行的引擎。但是,由于只要结果是正确的(匹配最左边最长的字符串),该标准就不强制执行该实现,因此该实现可以在NFA回溯引擎上彻底搜索与正则表达式匹配的所有字符串

    但是,至少GNU EGRP(基于文件名
    dfa.c


    请参考以下信息:

    • DFA
    • NFA仿真算法
    • NFA回溯
    有关更多详细信息,请参见(中引用)中的说明:

    • 对于(理论)正则表达式,存在具有子匹配跟踪(捕获组)的有效NFA仿真算法
    • 为什么回溯引擎如此突出(例如Java、Python、Perl2等)
      2:Perl实现了一个带有记忆的回溯引擎
    • 回溯引擎在输入长度上可能需要指数时间,而汤普森的NFA模拟算法需要O(mn)时间,其中m是正则表达式的长度,n是输入的长度
    • 目前已知的将(ir)正则表达式与反向引用匹配的最有效算法是回溯方法。因此,一些引擎决定不支持反向参考以提高匹配效率
    • 回溯引擎(即使有记忆)比汤普森的NFA模拟算法慢

    顺便说一下,re2引擎(如上所述)包括基于DFA和基于NFA(高效模拟)匹配算法的实现。

    感谢您的测试用例!你知道为什么第一个跑得更快吗?python internall是否将其减少到最小DFA?我无法控制此表达式的使用位置。他们要求。*在场。正则表达式不需要锚定到行的开头)。而且我不需要抓捕这群人。我不知道这是如何回答我的问题的:)你可以把这些澄清作为评论来问。答案是“我的直觉告诉我第二个更好”。当然,其余的可能是一个评论。:)@NHAHDH-感谢您提到这一点。我知道其中的区别和事实。我只提到了DFA,因为NFA至少在理论上等同于某些DFA。