Perl就像Python中的正则表达式

时间:2010-04-14 13:13:14

标签: python regex perl

在Perl中,我会做这样的事情,在regexp中使用不同的字段,用()分隔不同的字段并使用$

获取它们
foreach $line (@lines)
{
 $line =~ m/(.*?):([^-]*)-(.*)/;
  $field_1 = $1
  $field_2 = $2
  $field_3 = $3
}

我怎么能在Python中做这样的事情?

5 个答案:

答案 0 :(得分:18)

你的代码段的“Canonical”Python翻译......:

import re

myre = re.compile(r'(.*?):([^-]*)-(.*)')
for line in lines:
    mo = myre.search(line)
    field_1, field_2, field_3 = mo.groups()

导入re是必须的(导入通常在模块的顶部完成,但这不是强制性的)。预编译RE是可选的(如果您使用re.search函数,它将动态编译您的模式)但建议(因此您不依赖编译的RE对象的模块缓存来提高性能,还为了拥有一个RE对象并调用它的方法,这在Python中更为常见。

您可以使用match方法(从一开始就尝试匹配,无论您的模式是否以'^'开头)或search方法(尝试在任何地方进行匹配) ;用你给定的模式它们应该是等价的(但我不是100%肯定)。

.groups()方法返回所有匹配的组,因此您可以将它们全部分配到一个gulp(使用Python中的列表,就像在Perl中使用数组一样,可能更正常,但是因为您选择使用Perl中的标量你也可以用Python做同样的事情。)

如果任何行与RE不匹配,这将失败,如果你知道它们都匹配,那就没问题了(我不确定你的Perl的行为是什么,但我认为它会“重用”以前的相反,匹配线的值,这是奇特的......除非,你知道所有的线匹配;-)。如果您只想跳过不匹配的行,请将最后一个语句更改为以下两个:

    if mo:
        field_1, field_2, field_3 = mo.groups()

答案 1 :(得分:12)

在Perl中,使用数组比使用数字后缀一堆标量要好得多。 E.g。

foreach my $line ( @lines ) { 
    my @matches = ( $line =~ m/(.*?):([^-]*)-(.*)/ );
    ...
}

在Python中,re模块返回包含捕获组信息的匹配对象。所以你可以写:

match = re.search( '(.*?):([^-]*)-(.*)', line )

然后您的匹配将在match.group(1)match.group(2)

中提供

答案 2 :(得分:8)

Python支持使用re模块的正则表达式。 re.search()方法返回MatchObject,其中包含group()等方法,可用于检索“捕获组”信息。

例如:

m = re.search(r'(.*?):([^-]*)-(.*)', line)
field_1 = m.group(1)
field_2 = m.group(2)
field_3 = m.group(3)

答案 3 :(得分:6)

不要忘记在Python中,TIMTOWTDI;)

import re
p = re.compile(r'(\d+)\.(\d+)')
num_parts = p.findall('11.22   333.444') # List of tuples.
print num_parts                          # [('11', '22'), ('333', '444')]

答案 4 :(得分:5)

正如另一个例子,python为named capture groups提供了非常好的支持(事实上python开创了对命名捕获组的支持)。

要使用命名捕获组,只需在捕获组的左括号内添加?P<the_name_of_the_group>即可。

这使您可以非常轻松地在字典中获取所有匹配项:

>>> import re
>>> x = re.search("name: (?P<name>\w+) age: (?P<age>\d+)", "name: Bob age: 20")
>>> x.groupdict()
{'age': '20', 'name': 'Bob'}

以下是OP的示例,已修改为使用命名捕获组

import re

find_fields_regex = re.compile(r'(?P<field1>.*?):(?P<field2>[^-]*)-(?P<field3>.*)')
for line in lines:
    search_result = find_fields_regex.search(line)
    all_the_fields = search_result.groupdict()

现在all_the_fields是一个字典,其中的键对应于捕获组名称(&#34; field1&#34;,&#34; field2&#34;和&#34; field3&#34;)和对应于各个捕获组的内容的值。

为什么您应该更喜欢命名捕获组

  • 对于已命名的捕获组,如果您修改正则表达式模式以添加更多捕获组或删除现有捕获组并不重要,那么所有内容仍然会在正确的密钥下放入字典中。但是,如果没有命名捕获组,则每次组数更改时都必须仔细检查变量赋值。
  • 命名捕获组使您的捕获组自我记录。
  • 如果需要,您仍然可以使用数字来引用这些组:
>>> import re
>>> x = re.search("name: (?P<name>\w+) age: (?P<age>\d+)", "name: Bob age: 20")
>>> x.groupdict()
{'age': '20', 'name': 'Bob'}
>>> x.group(1)
'Bob'
>>> x.group(2)
'20'

一些优秀的正则表达式资源: