使用用户定义的布尔值设置Python正则表达式标志的最佳方法

时间:2018-11-12 18:21:27

标签: python regex

我正在使用python构建正则表达式检查工具,用户可以在其中创建模式,检查他/她需要的标志,然后使用生成的模式测试不同的字符串。 Python有6个正则表达式标志:re.I,re.M,re.S,re.U,re.L和re.X,因此由于所有这些组合,编写if-else语句将是一场噩梦。

有没有一种方法可以将标志定义为布尔值呢?像这样:

re.compile(pattern, re.IGNORECASE=ignorecase, re.MULTILINE=multiline, ...)

上面的代码不起作用,但希望可以使它变得清楚。 patternignorecasemultiline都是用户使用简单形式定义的变量,其中包含模式的输入和标志的复选框。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您需要的是一种方便的方法,将启用的标志合并为一个可以传递的参数。我建议不要简单地检查设置的内容(以您已经执行过的任何方式),然后立即将相应的标志合并到单个累加器变量中,而不是为每个标志设置不同的值。

例如,假设标志被指定为命令行参数,我可以这样做:

userchoices = 0
if "-a" in opts:
    userchoices |= re.A
if "-i" in opts:
    userchoices |= re.I
if "-L" in opts:
    userchoices |= re.L
etc.

matcher = re.compile(pattern, flags=userchoices)

如果您已经编写了将每个命名变量初始化为相应的re.?常量的代码,则可以将它们简单地收集到一个数组中,或像这样将它们或在一起:

from operator import or_
from functools import reduce
userchoices = reduce(or_, [asciionly, ignorecase, multiline, ...])

根据您检测用户选择的方式,您可以通过例如使用字典将表单的选项映射到python常量等。

PS。一种替代方法:每个标志都可以由相应的字母表示,并嵌入到regexp本身中。因此,您可以执行以下操作,并完全绕过flags参数:

userflags = "".join([asciionly, ignorecase, multiline, ...])
matcher = re.compile("(?%s)%s" % (userflags, pattern) )

老实说,我认为这有点hacky,但是由于regexp封装了正在使用的设置,因此可能存在一个地方。