Perl就像Python中的正则表达式

ana*_*nsi 10 python regex perl

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

foreach $line (@lines)
{
 $line =~ m/(.*?):([^-]*)-(.*)/;
  $field_1 = $1
  $field_2 = $2
  $field_3 = $3
}
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*lli 19

您的代码段的"Canonical"Python翻译...:

import re

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

导入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()
Run Code Online (Sandbox Code Playgroud)


fri*_*edo 13

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

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

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

match = re.search( '(.*?):([^-]*)-(.*)', line )
Run Code Online (Sandbox Code Playgroud)

那么你的比赛将是可用的match.group(1),match.group(2)等等.


Ada*_*kin 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)
Run Code Online (Sandbox Code Playgroud)


FMc*_*FMc 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')]
Run Code Online (Sandbox Code Playgroud)


lfa*_*lin 5

正如另一个例子,python为命名捕获组提供了非常好的支持(事实上​​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'}
Run Code Online (Sandbox Code Playgroud)

这是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()
Run Code Online (Sandbox Code Playgroud)

现在all_the_fields是具有对应于捕获组名称("field1","field2"和"field3")的键的字典以及对应于各个捕获组的内容的值.

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

  • 对于命名的捕获组,如果您修改正则表达式模式以添加更多捕获组或删除现有捕获组并不重要,所有内容仍然会在正确的键下放入字典中.但是,如果没有命名捕获组,则每次组数更改时都必须仔细检查变量赋值.
  • 命名捕获组使您的捕获组自我记录.
  • 如果需要,您仍然可以使用数字来引用组:
>>> 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'
Run Code Online (Sandbox Code Playgroud)

一些好的正则表达式资源: