在Python中分配和测试Regex?

2024-06-16 11:04:34 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的许多python项目中,我发现自己必须遍历一个文件,将行与regex匹配,然后根据regex提取的行中的元素执行一些计算。你知道吗

在伪C代码中,这非常简单:

while (read(line))
{
    if (m=matchregex(regex1,line))
    {
         /* munch on the components extracted in regex1 by accessing m */
    }
    else if (m=matchregex(regex2,line))
    {
         /* munch on the components extracted in regex2 by accessing m */
    }
    else if ...
    ...
    else
    {
         error("Unrecognized line format");
    }
}

但是,因为python不允许if的条件赋值,所以这不能很好地完成。可以先对所有正则表达式进行解析,然后对各种匹配对象执行if,但这既不优雅也不高效。你知道吗

相反,我发现自己在每个项目的底层都包含了这样的代码:

im=None
img=None
def imps(p,s):
    global im
    global img
    im=re.search(p,s)
    if im:
        img=im.groups()
        return True
    else:
        img=None
        return False

然后我可以这样工作:

for line in open(file,'r').read().splitlines():
    if imps(regex1,line):
        # munch on contents of img
    elsif imps(regex2,line):
        # munch on contents of img
    else:
        error('Unrecognised line: {}'.format(line))

这是工作,是合理的紧凑,易于键入。但它并不漂亮;它使用全局变量,并且不是线程安全的(到目前为止,这对我来说还不是一个问题)。你知道吗

但我相信其他人以前也遇到过这个问题,并提出了一个同样紧凑、但更python-y和一般更优秀的解决方案。它是什么?你知道吗


Tags: 项目代码innoneimgifonline
2条回答

取决于代码的需要。你知道吗

我常用的一种选择是这样的:

# note, order is important here. The first one to match will exit the processing
parse_regexps = [
    (r"^foo", handle_foo),
    (r"^bar", handle_bar),
]

for regexp, handler in parse_regexps:
    m = regexp.match(line)
    if m:
        handler(line)  # possibly other data too like m.groups
        break
else:
    error("Unrecognized format....")

这样做的好处是将处理代码移动到清晰和明显的函数中,从而使测试和更改变得容易。你知道吗

您可以使用continue

for line in file:
    m = re.match(re1, line)
    if m:
       do stuff
       continue

    m = re.match(re2, line)
    if m:
       do stuff
       continue

    raise BadLine

另一个不太明显的选择是使用如下函数:

def match_any(subject, *regexes):
    for n, regex in enumerate(regexes):
        m = re.match(regex, subject)
        if m:
           return n, m
    return -1, None

然后:

for line in file:
    n, m = match_any(line, re1, re2)
    if n == 0:
       ....
    elif n == 1:
       ....
    else:
       raise BadLine

相关问题 更多 >