繁体   English   中英

Python中的Perl模式匹配

[英]Perl pattern matching in 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)

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

出于记录,您可以使用元组拆包来使其更加简洁:

var1, var2 = mySearch.groups()

更新:

元组拆包

元组解包是Python中的一项有用功能。 为了理解它,我们首先要问什么是元组 元组从本质上讲是一个不可变的序列-与列表不同,您不能追加或弹出或任何此类填充。 语法上,声明元组非常简单-只是几个用逗号分隔的值。

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()

首先,要认识到这两个语句,您的具体情况-在mySearchMatchObject从正则表达式产生有两个匹配的组-完全是功能上等同。

在元组拆包的性质方面,它们仅相差很小。 第一个在右边声明一个元组,第二个使用MatchObject.groups返回的元组。

这并不是真的适用于您的情况,但是了解MatchObject.groupMatchObject.groups行为略有不同可能会很有用(请参见此处此处 )。 MatchObject.groups返回正则表达式遇到的所有“子组”(即捕获组),而MatchObject.group返回单个组并将整个模式作为可访问的组进行计数。

实际上,对于这种情况,您应该使用您认为最能表达或最清晰的这两种方式中的任何一种。 我个人认为在右侧提到组1和2是多余的,而MatchObject.groups(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

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

var1, var2 = mySeach.groups()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM