使用全局标志进行Python正则表达式编译

6 投票
2 回答
10862 浏览
提问于 2025-04-16 22:53

有没有办法定义一个全局标志,让Python的re.compile()自动设置这个标志呢?比如说,我想在一个类里,所有的正则表达式都使用re.DOTALL这个标志。

这听起来可能有点奇怪,但我其实无法控制这部分代码,因为它是由YAPPS生成的。我只是给YAPPS提供一个包含正则表达式的字符串,然后它会调用re.compile()。可惜的是,我需要在re.DOTALL模式下使用它。

一个快速的解决办法是编辑生成的解析器,添加合适的选项。但我还是希望能有其他更自动化的方法来实现这个。

补充说明:Python允许你使用(?...)的结构来设置标志,所以在我的情况下,re.DOTALL可以用(?s)来表示。虽然这样很有用,但它并不能应用于整个类或者整个文件。

所以我的问题依然存在。

2 个回答

8

所有的标志都可以直接在正则表达式里设置:

r"(?s)Your.*regex.*here"
12

是的,你可以把它设置为全局的 re.DOTALL。但是你不应该这样做。全局设置在任何时候都是个坏主意——这可能会导致同一个Python实例运行的其他代码出错。


所以,不要这样做

你可以利用Python解释器每个实例都会缓存模块的特点,这样如果其他人导入同一个模块,他们也会得到你可以访问的那个对象。所以你可以把 re.compile 重新绑定到一个代理函数,这个函数会传递 re.DOTALL

import re
re.my_compile = re.compile
re.compile = lambda pattern, flags: re.my_compile(pattern, flags | re.DOTALL)

这样一来,所有其他人也会受到这个改变的影响。

你甚至可以把这个封装在一个上下文管理器里,像这样:

from contextlib import contextmanager

@contextmanager
def flag_regexen(flag):
    import re
    re.my_compile = re.compile
    re.compile = lambda pattern, flags: re.my_compile(pattern, flags | flag)
    yield
    re.compile = re.my_compile

然后

with flag_regexen(re.DOTALL):
    <do stuff with all regexes DOTALLed>

撰写回答