簡體   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