Python字符串与多个正则表达式比较
我对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
,这个类负责进行匹配,存储匹配的结果,并返回一个布尔值来表示成功或失败。这个方法产生的代码最容易理解,适合这个目的。