代码之家  ›  专栏  ›  技术社区  ›  Nate

使小型正则表达式更具可读性

  •  3
  • Nate  · 技术社区  · 14 年前

    我有一个有效的正则表达式,但是我想让它更可读一点,而且我离正则表达式专家还很远,所以我谦虚地希望得到一些提示。

    它被设计用来抓取几个不同的编译器、链接器和其他构建工具的输出,并用来构建一个漂亮的夏季小报告。它确实很好,但我觉得自己写的时候很笨拙,我宁愿学也不想把它弄错。

    (.*?)\s?:?\s?(informational|warning|error|fatal error)?\s([A-Z]+[0-9][0-9][0-9][0-9]):\s(.*)$
    

    简单地分解如下:

    (.*?)                                       # non-greedily match up until...
    \s?:?\s?                                    # we come across a possible " : "
    (informational|warning|error|fatal error)?  # possibly followed by one of these
    \s([A-Z]+[0-9][0-9][0-9][0-9]):\s           # but 100% followed by this alphanum
    (.*)$                                       # and then capture the rest
    

    我对上面的第二和第四条更感兴趣…美丽的。出于某种原因,我使用的regex测试仪(调节器)与普通空格不匹配,所以我必须使用…但这并不意味着与任何其他空白相匹配。

    任何学校教育都将受到极大的赞赏。

    3 回复  |  直到 14 年前
        1
  •  2
  •   Mark Byers    14 年前

    第2行

    我认为你的正则表达式与注释不匹配。您可能需要这样做:

    (\s:\s)?
    

    要使其不捕获:

    (?:\s:\s)?
    

    应该 能够使用文本空间而不是 \s . 这一定是您使用的工具的限制。

    第4行

    [0-9][0-9][0-9][0-9] 可替换为 [0-9]{4}

    在某些语言中 [0-9] 等于 \d .

        2
  •  4
  •   Daniel Vandersluis    14 年前

    使长regex更具可读性的最简单方法是使用“ free-spacing “(或) \x ) modifier 这将允许您像在第二个代码块中那样编写regex——这会使空白区被忽略。但是,这并不受所有引擎的支持(根据上面链接的页面,.NET、Java、Perl、露比、Python、XPath和XPath支持它)。

    还要注意,在自由间距模式下,可以使用 [ ] 而不是 \s 如果你只想匹配一个空格字符(除非你使用Java,在这种情况下你必须使用)。 \ ,这是一个转义空间)。

    如果希望每个元素独立于其他元素都是可选的,那么第二行实际上没有任何功能,但是第四行可以缩短:

    \s([A-Z]+\d{4}):\s
    

    \d 是一个 shorthand class 相当于 [0-9] {4} 指定它应该出现 exactly four times

    第三行也可以稍微缩短一些。( (?:…) 指定 不捕获 group ):

    (informational|warning|(?:fatal )? error)?
    

    从效率的角度来看,除非每次使用括号时实际上需要捕获子模式,否则可以删除所有子模式,但第三行除外,其中需要使用括号 alternation )--但那一个可以不捕获。把这些放在一起,你会得到:

    .*?
    \s?:?\s?
    (?:informational|warning|(?:fatal )?error)?
    \s[A-Z]+\d{4}:\s
    .*$
    
        3
  •  0
  •   zigdon    14 年前

    也许您可以从子表达式构建re,以便您的最终re看起来像这样:

     /$preamble$possible_colon$keyword$alphanum$trailer/