映射正则表达式组匹配

时间:2017-11-01 18:26:18

标签: python regex

我希望匹配正则表达式\(.*\)\[.*\]\{.*\}\<.*\>。有没有办法组合这些正则表达式?

例如,我想到的是: ([\(\[\{\<]).*\1,但当然匹配\(.*\(\[.*\[\{.*\{\<.*\<

我的目标是能够匹配以前的正则表达式组,但在匹配之前将一个函数应用于该组。

考虑:

def match_pairs(pairs):
    re = '|'.join("({begin}.*{end})".format(begin=beg, end=end) for (beg, end) in pairs)
    return re

我正在考虑使用与上述函数类似的东西,但理想情况下这个函数不会返回一个非常长的正则表达式。如果您认为这个问题没有任何实际价值,请告诉我。我仍然很想知道Python3是否支持这样的任何功能,有点像re.sub可以将一个函数作为替代。如果不存在此类功能,我如何编写match_pairs以便它可以将["()", "[]", "[]", "{}"]作为参数?

1 个答案:

答案 0 :(得分:1)

此任务的明显(和最短)正则表达式为\(.*\)|\[.*\]|\{.*\}|\<.*\>

缺点是您有.*子模式的四个副本,因此如果您需要更改它,则必须在4个位置更改它。幸运的是,我们可以通过使用捕获组来解决这个问题:

(?:\(()|\[()|\{()|<()).*(?:\1\)|\2\]|\3\}|\4>)

Online demo.

这可能看起来令人困惑,但实际上非常简单。模式构建如下:

(?:opening_char_1()|opening_char_2()|...).*(?:\1closing_char_1|\2closing_char_2|...)

这使用了一个相当简单的小技巧:每个开场角色(([{<)都附带一个捕获组,如下所示:{{ 1}}。这允许我们“记住”哪个开头字符匹配 - 如果捕获组1匹配,我们知道开头字符是\[()。如果捕获组2匹配,则开头字符为(,依此类推。所以我们只需使用反向引用([\1等)来找出开头字符是什么,然后匹配相应的结束字符。