Python中的Perl模式匹配

时间:2015-04-11 04:05:55

标签: python

我是Perl用户多年,最近开始使用Python。

我了解到,总有一种明显的方式"做某些事情。我希望检查一下"一个"将我在Perl中的编码风格转换为Python的方法。谢谢!

目标是:

  • 检测模式的存在
  • 如果找到,则提取模式的某些部分

的Perl:

if ($str =~ /my(pat1)and(pat2)/) {
    my ($var1, $var2) = ($1, $2);
}

据我学习Python,下面就是我现在的编码方式。它似乎比Perl采取更多步骤。这就是我怀疑我的Python代码的原因。

mySearch = re.search ( r'my(pat1)and(pat2)', str )
if mySearch:
    var1 = mySearch.group(1)
    var2 = mySearch.group(2)

3 个答案:

答案 0 :(得分:2)

Python不像perl那样优先考虑模式匹配和字符串操作。这些都是类似的模式,是的,Python的时间更长(它也有很多很棒的东西,比如它的OOP,并没有使用奇怪的神奇全局变量)。

但是对于记录,您可以使用元组解包来使其更简洁:

var1, var2 = mySearch.groups()

<强>更新

元组拆包

元组解包是Python中的一个有用功能。要理解它,我们首先要问一下,tuple是什么。一个元组的核心是一个不可变的序列 - 与列表不同,你不能追加或弹出或任何这些东西。从语法上讲,声明一个元组非常简单 - 它只是用逗号分隔的几个值。

my_tuple = "I", "am", "awesome"
my_tuple[0]  # "I"
my_tuple[1]  # "am"
my_tuple[2]  # "awesome"

人们通常认为元组实际上是由周围的括号定义的 - my_tuple = ("I", "am", "awesome") - 但这是错误的;括号只有在澄清或执行某种操作顺序时才有用。

元组解包是Python中最甜蜜的功能之一。您可以在左侧定义包含未定义名称的元组数据结构,然后将右侧的iterable解压缩到其中。右侧可以包含任何iterable,但其包含数据的形状必须与左侧名称的元组结构完全匹配。

# some_var and other_var are both undefined
print some_var  # NameError: some_var is undefined
print other_var  # NameError: other_var is undefined
my_iterable = ["so", "cool"]

# note that 'some_var, other_var' looks a whole lot like a tuple
some_var, other_var = my_iterable
print some_var  # "so"
print other_var  # "cool" 

同样,我们不需要右边的列表,但任何类型的可迭代 - 例如,生成器:

def some_generator():
     yield 1
     yield 2
     yield 3

a, b, c = some_generator()
print a  # 1
print b  # 2
print c  # 3

您甚至可以使用嵌套数据结构进行元组解包。

nested_list = [1, [2, 3], 4]
# note that parentheses are necessary here to delimit tuples
a, (b, c), d = nested_list 

如果右侧上的可迭代不匹配左侧的模式,事情就会爆发:

# THESE EXAMPLES DON'T WORK
a, b = [1, 2, 3]  # ValueError: too many values to unpack
a, b = []  # ValueError: need more than 0 values to unpack

实际上,当我认为iterable只有一个项目并且我希望我的代码失败时,这个嘈杂的失败使元组解压缩我最喜欢的方式从iterable获取项目有不止一个。

# note that the left side below is how you define a tuple of one  
bank_statement, = bank_statements  # we def want to blow up if too many statements

多个作业

人们认为多重任务实际上只是简单的元组拆包。

a, b = 1, 2
print a  # 1
print b  # 2

这没什么特别的。解释器将等式的右侧评估为tuple - 记住,元组只是用逗号分隔的值(文字,变量,求值函数调用,等等) - 然后解释器将它与左侧,就像上面的所有例子一样。

将它带回家

我写这篇文章是为了解释你为这个问题得到的两个不同答案:

var1, var2 = mySearch.group(1), mySearch.group(2)

var1, var2 = mySearch.groups()

首先,要认识到这两个陈述,对于您的情况 - mySearch是由具有两个匹配组的正则表达式产生的MatchObject - 完全在功能上是等效的。

它们在元组拆包的性质方面只有很小的区别。第一个在右边声明一个元组,而第二个使用MatchObject.groups返回的元组。

这并不适用于您的情况,但了解MatchObject.groupMatchObject.groups的行为略有不同(请参阅herehere)可能会有所帮助。 MatchObject.groups返回正则表达式遇到的所有“子组” - 即捕获组 - MatchObject.group返回单个组,并将整个模式计为可在0处访问的组。

实际上,对于这种情况,您应该使用您认为最具表现力或最清晰的两种情况。我个人认为在右侧提及第1组和第2组是多余的,我常常被MatchObject.groups(0)返回与整个模式匹配的字符串这一事实所困扰,从而将所有“子组”抵消为一个索引。 / p>

答案 1 :(得分:0)

在Python中,您可以在一行中使用逗号作为分隔符执行多个变量赋值。

var1, var2 = mySearch.group(1), mySearch.group(2)

其他答案说关于元组拆包。因此,如果要将所有捕获的组内容提取到变量,那样会更好。如果你想获取特定的组内容,你必须要采用我提到的方法。

va1, var2, var3 = mySearch.group(2), mySearch.group(3), mySearch.group(1)

示例:

>>> import re
>>> x = "foobarbuzzlorium"
>>> m = re.search(r'(foo)(bar.*)(lorium)', x)
>>> if m:
        x, y = m.group(1), m.group(3)
        print(x,y)


foo lorium

答案 2 :(得分:0)

您可以一次提取所有组并将它们分配给变量:

var1, var2 = mySeach.groups()