Python字符串与多个正则表达式比较

6 投票
4 回答
6449 浏览
提问于 2025-04-15 21:34

我对Perl和Ruby比较熟悉,但对Python还不太了解,所以希望有人能教我用Python的方式来完成以下任务。我想把几行文本和多个正则表达式进行比较,并提取出匹配的部分。在Ruby中,大概是这样的:

# Revised to show variance in regex and related action.
data, foo, bar = [], nil, nil
input_lines.each do |line|
  if line =~ /Foo(\d+)/
    foo = $1.to_i
  elsif line =~ /Bar=(.*)$/
    bar = $1
  elsif bar
    data.push(line.to_f)
  end
end

我在Python中的尝试看起来有点复杂,因为匹配的部分是通过对正则表达式进行匹配或搜索来得到的,而Python在条件语句或开关语句中没有赋值的功能。那么,用Python的方式来处理这个问题应该怎么做呢?

4 个回答

1

在Python中,有几种方法可以“动态绑定名称”,比如我以前的一个做法,叫做“赋值并测试”;在这种情况下,我可能会选择另一种方法(假设使用的是Python 2.6,如果你用的是旧版本的Python,需要稍微改动一下),像这样:

import re
pats_marks = (r'^A:(.*)$', 'FOO'), (r'^B:(.*)$', 'BAR')
for line in lines:
    mo, m = next(((mo, m) for p, m in pats_mark for mo in [re.match(p, line)] if mo),
                 (None, None))
    if mo: print '%s: %s' % (m, mo.group(1))
    else: print 'NO MATCH: %s' % line

当然,很多小细节可以调整,比如我选择了(.*)而不是(.*?)作为匹配组——因为在后面有$的情况下,它们是等价的,所以我选择了更简短的形式;-) 你也可以预编译正则表达式,或者用不同的方式组织数据,比如用一个字典来根据正则表达式模式索引等等。

但我认为重要的想法是,让结构以数据驱动的方式来处理,并且通过子表达式for mo in [re.match(p, line)]动态绑定匹配对象的名称,这实际上是在一个只有一个元素的列表上进行“循环”(生成表达式只通过循环来绑定名称,而不是通过赋值——有些人认为使用这一部分生成表达式的规范有点“棘手”,但我认为这是一个完全可以接受的Python用法,尤其是因为在设计列表推导式时,这种用法就已经被考虑过了)。

1

像这样,但看起来更好看:

regexs = [re.compile('...'), ...]

for regex in regexes:
  m = regex.match(s)
  if m:
    print m.groups()
    break
else:
  print 'No match'
0

保罗·麦圭尔的解决方案是使用一个中间类 REMatcher,这个类负责进行匹配,存储匹配的结果,并返回一个布尔值来表示成功或失败。这个方法产生的代码最容易理解,适合这个目的。

撰写回答