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

问题描述 投票:0回答:1

这个问题在这里已有答案:

我正在使用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都是由用户使用包含模式输入的简单表单定义的变量,以及标志的复选框。

任何帮助表示赞赏。

python regex
1个回答
0
投票

您需要的是一种方便的方法,可以将启用的标志组合成一个可以传递的参数。我建议只检查设置的内容(以任何方式执行此操作),并立即将相应的标志合并为单个累加器变量,而不是为每个标志设置不同的值。

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

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封装了它所使用的设置,所以可能有它的位置。

© www.soinside.com 2019 - 2024. All rights reserved.