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

6

我对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

因为在正则表达式的match/search调用中匹配组是返回的,而Python没有条件语句或switch语句中的赋值,所以我的Python尝试变得相当丑陋。那么,如何以Pythonic的方式解决(或思考)这个问题?


1
请参见https://dev59.com/6nE85IYBdhLWcg3w436o。 - PaulMcG
是的,那个问题正是我在寻找的 - 谢谢! - maerics
4个回答

1

类似这样,但更漂亮:

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

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

1
我尝试了类似的东西,但我想根据匹配的正则表达式采取不同的操作,因此我从列表转移到了将正则表达式映射到lambda函数的字典,以便在找到匹配项时调用,但这会导致一些混乱的代码... - maerics

1

在Python中有几种“动态绑定名称”的方法,例如我旧的recipe,“赋值并测试”,在这种情况下,我可能会选择另一种方法(假设使用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

当然,许多细节可以进行调整(例如,我只选择了(.*)而不是(.*?)作为匹配组——在紧随其后的$给定的情况下它们是等效的,因此我选择了较短的形式;-)——您可以预编译RE、以不同于pats_mark元组的方式分解事物(例如,使用按RE模式索引的字典等)等。

但是,我认为实质性的想法是使结构数据驱动,并使用子表达式for mo in [re.match(p, line)]将匹配对象即时绑定到名称上,这是一个“循环”单个项目列表(genexps仅通过循环绑定名称,而不是通过赋值——一些人认为使用genexps规范中的这一部分是“棘手”的,但我认为这是一个完全可接受的Python习惯用法,特别是因为它在设计列表推导式、genexps的“祖先”之一的时候就被考虑过了)。


0

Paul McGuire的解决方案使用中间类REMatcher执行匹配,存储匹配组,并返回成功/失败的布尔值,结果证明对于此目的而言,它产生了最易读的代码。


-1

你的正则表达式只是从第三个字符之后获取所有内容。

for line in open("file"):
    if line.startswith("A:"):
        print "FOO #{"+line[2:]+"}"
    elif line.startswith("B:"):
        print "BAR #{"+line[2:]+"}"
    else:
        print "No match"

不错的方式,但我会使用split和比较:begin, rest = line.split(':', 1) if begin == "A": 等等... - moshez
这很不错,但我正在寻找更通用的东西,简单的正则表达式只是为了说明目的,实际的正则表达式会相当复杂。 - maerics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接