简化冗长的Python正则表达式

11 投票
1 回答
615 浏览
提问于 2025-04-17 15:56

我有一个很啰嗦的Python正则表达式字符串(里面有很多空格和注释),我想把它转换成“正常”的样子(为了导出到JavaScript)。特别是,我需要这个转换非常可靠。如果有任何可以证明是正确的方法,那就是我想要的。例如,一个简单的实现可能会把像r' \# # A literal hash character'这样的正则表达式搞坏,这可不行。

最好的办法是让Python的re模块给我返回一个不那么啰嗦的正则表达式表示,但我找不到这样的方法。

1 个回答

8

我认为要简化一个冗长的正则表达式,只需要解决这两个问题:

  1. 删除行末的注释
  2. 删除未转义的空格

试试这个,它通过两个不同的正则替换来完成这两个步骤:

import re

def unverbosify_regex_simple(verbose):
    WS_RX = r'(?<!\\)((\\{2})*)\s+'
    CM_RX = r'(?m)(?<!\\)((\\{2})*)#.*$'

    return re.sub(WS_RX, "\\1", re.sub(CM_RX, "\\1", verbose))

上面的代码是一个简化版本,保留了转义的空格。虽然结果可能看起来有点难读,但应该能在正则表达式平台上正常工作。

另外,如果你想要一个稍微复杂一点的答案,可以“取消转义”空格(也就是说,把'\ '变成' '),这样得到的结果应该更符合大多数人的预期:

import re

def unverbosify_regex(verbose):
    CM1_RX = r'(?m)(?<!\\)((\\{2})*)#.*$'
    CM2_RX = r'(\\)?((\\{2})*)(#)'
    WS_RX  = r'(\\)?((\\{2})*)(\s)\s*'

    def strip_escapes(match):
        ## if even slashes: delete space and retain slashes
        if match.group(1) is None:
            return match.group(2)

        ## if number of slashes is odd: delete slash and keep space (or 'comment')
        elif match.group(1) == '\\':
            return match.group(2) + match.group(4)

        ## error
        else:
            raise Exception

    not_verbose_regex = re.sub(WS_RX, strip_escapes,
                          re.sub(CM2_RX, strip_escapes,
                            re.sub(CM1_RX, "\\1", verbose)))

    return not_verbose_regex

更新: 添加了注释来解释奇偶斜杠的计数。修正了CM_RX中的第一个组,以便在斜杠计数为奇数时保留完整的“注释”。

更新 2: 修正了注释的正则表达式,之前没有正确处理转义的井号。现在应该能处理“\# #转义的井号”和“# 带有\#转义井号的注释”以及“\\# 注释”。

更新 3: 添加了一个简化版本,不会清理转义的空格。

更新 4: 进一步简化,消除了可变长度的负向前瞻(以及反向/反向技巧)。

撰写回答