Python正規表示式完全指南

2023-06-13 12:00:33

本篇文章將深入探討python的一項強大工具:正規表示式。正規表示式是一個強大的文書處理工具,可以用來匹配,搜尋,替換和解析文字。我們將逐步展示如何在Python中使用正規表示式,包括其基本語法,常見用法和一些高階技巧。而在最後的「one more thing」部分,我們將探索一個不為人知但又非常有用的正規表示式的技巧。

簡單正規表示式匹配

在Python中,re模組提供了正規表示式的支援。我們先從最簡單的字元匹配開始。

import re

# 檢查字串是否包含字母"a"
txt = "Hello, world!"
match = re.search("a", txt)
print(match)  # 輸出:None,因為"a"沒有在字串中

在這個例子中,我們使用了re.search()函數來查詢字串中是否包含"a"。這是最基礎的字元匹配,但已經可以看出正規表示式的用處。例如,你可以用這種方式檢查一個電子郵件地址是否包含"@"。

使用元字元

正規表示式的真正威力在於其元字元的使用,比如.*?[]等等。下面的例子展示瞭如何使用.(點)元字元匹配任何字元(除了新行)。

txt = "Hello, world!"
match = re.search("H.llo", txt)
print(match.group())  # 輸出:Hello

在這個例子中,.字元匹配了"e",使得"H.llo"可以匹配"Hello"。

使用預定義的字元集

有時我們希望匹配的是一類字元,而不是單個字元。比如,我們可能想要匹配任何數位。Python的正規表示式提供了預定義的字元集來實現這種功能。\d就代表任何數位。

txt = "123 Hello, world!"
match = re.search("\d+", txt)
print(match.group())  # 輸出:123

在這個例子中,\d+匹配了一串數位"123"。

分組和捕獲

我們可以使用圓括號()建立子模式或組,並使用group()方法來捕獲這些組。

txt = "123 Hello, world!"
match = re.search("(\d+) (Hello),", txt)
print(match.group(1))  # 輸出:123
print(match.group(2))  # 輸出:Hello

使用正向先行斷言

這是一個高階技巧,它允許我們在不消耗字元的情況下進行匹配。例如,我們可能想找出所有以句號結束但不包含句號的句子。

txt = "Hello. My name is Python. Nice to meet you."
matches = re.findall(".*?(?=\\.)", txt)
for match in matches:
    print(match)  # 輸出:Hello,My name is Python,Nice to meet you

在這個例子中,.*?(?=\\.)匹配了所有以句號結束的句子,但並沒有消耗句號。

字元集和範圍

我們之前討論過預定義的字元集,比如\d。但有時我們可能需要自定義字元集,我們可以使用方括號[]來達成這個目標。例如,我們可以建立一個只包含小寫字母的字元集。

txt = "Hello, World!"
match = re.search("[a-z]+", txt)
print(match.group())  # 輸出:ello

在這個例子中,[a-z]+匹配了一串連續的小寫字母"ello"。注意"Hello"的首字母"H"由於是大寫,沒有被匹配。

貪婪匹配和非貪婪匹配

Python的正規表示式預設是貪婪的,這意味著它們會盡可能匹配更多的字元。但有時我們可能希望進行非貪婪匹配。我們可以通過在量詞後面新增問號?來實現這個功能。

txt = "12345"
match = re.search("\d+?", txt)
print(match.group())  # 輸出:1

在這個例子中,\d+?進行了非貪婪匹配,只匹配了一個數位"1"。

零寬斷言

零寬斷言允許我們在字元之間設定條件。比如,我們可以使用(?<=a)b來匹配所有在"a"後面的"b"。

txt = "cab, dab"
matches = re.findall("(?<=a)b", txt)
for match in matches:
    print(match)  # 輸出:b,b

在這個例子中,(?<=a)b匹配了所有在"a"後面的"b"。

使用編譯的正規表示式

如果你的程式需要多次使用同一個正規表示式,你可以將其編譯為一個正規表示式物件。這可以提高程式碼的執行效率。

pattern = re.compile("\d+")
txt = "123 Hello, world!"
match = pattern.search(txt)
print(match.group())  # 輸出:123

在這個例子中,我們先編譯了正規表示式\d+,然後使用pattern.search()方法來進行匹配。

One More Thing

到現在為止,我們已經探討了Python正規表示式的基礎知識。但是在這最後的"One More Thing"部分,我想分享一個不常被提及,但在處理複雜文字模式時非常有用的技巧:命名組

命名組允許我們給匹配的組分配一個名字,然後在後面的程式碼中參照它。這在處理複雜的模式匹配時非常有用。

txt = "James: 1234567890"
match = re.search("(?P<name>\w+): (?P<phone>\d+)", txt)
print(match.group('name'))  # 輸出:James
print(match.group('phone'))  # 輸出:1234567890

在這個例子中,我們使用了命名組(?P<name>\w+)(?P<phone>\d+)來匹配名字和電話號碼,並使用group()方法來獲取它們。

正規表示式是一個非常強大的工具,希望本篇文章能幫你掌握它在Python中的用法。

如有幫助,請多關注
個人微信公眾號:【Python全視角】
TeahLead_KrisChang,10+年的網際網路和人工智慧從業經驗,10年+技術和業務團隊管理經驗,同濟軟體工程本科,復旦工程管理碩士,阿里雲認證雲服務資深架構師,上億營收AI產品業務負責人。