在 Perl 中,我会像这样使用正则表达式来获取不同的字段,将不同的字段用 () 分隔,并使用 $ 获取它们。
foreach $line (@lines)
{
$line =~ m/(.*?):([^-]*)-(.*)/;
$field_1 = $1
$field_2 = $2
$field_3 = $3
}
我该如何在Python中实现这样的功能?
您代码片段的“规范”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()
方法返回所有匹配组,因此您可以一次性将它们全部分配(在Python中使用列表,就像在Perl中使用数组一样,可能更正常,但由于您选择在Perl中使用标量,因此在Python中也可以采用相同的方式)。
如果任何行不匹配RE,则会引发异常,这样做可以知道所有行都匹配(我不确定您的Perl的行为是什么,但我认为它会“重用”上一个匹配行的值,这是奇怪的...除非,再次强调您知道所有行都匹配;-)。如果您只想跳过不匹配的行,请将最后一个语句更改为以下两个语句:
if mo:
field_1, field_2, field_3 = mo.groups()
在Perl中,使用数组比用数字后缀一堆标量要好得多。例如:
foreach my $line ( @lines ) {
my @matches = ( $line =~ m/(.*?):([^-]*)-(.*)/ );
...
}
在Python中,re
模块返回一个包含捕获组信息的匹配对象。因此你可以这样写:
match = re.search( '(.*?):([^-]*)-(.*)', line )
那么你的匹配结果将会在 match.group(1)
、match.group(2)
等中得到。
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)
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')]
?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'}
以下是原帖作者的示例,已修改为使用命名捕获组
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
是一个字典,其中键对应于捕获组名称("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'
一些优秀的正则表达式资源:
import this
(也就是Python之禅,或者直接运行python -c "import this" | grep -i there
)就可以明白了。 - Aleksi Torhamo