Python: 正則表達式

正則表達式是處理文本數據的強大工具,Python通過re模塊提供了完整的正則表達式功能。本文將詳細介紹Python正則表達式的使用方法,包括基礎語法、高級技巧和re模塊API的詳細解析。

一、正則表達式基礎

1.1 什么是正則表達式

正則表達式(Regular Expression)是一種用于匹配字符串中字符組合的模式,可以用于搜索、替換和驗證文本數據。

1.2 Python中的re模塊

Python通過內置的re模塊提供正則表達式支持:

import re

二、正則表達式基本語法

2.1 普通字符

大多數字母和字符只會匹配它們自身:

pattern = r"hello"
text = "hello world"
match = re.search(pattern, text)
if match:print("找到匹配:", match.group())  # 輸出: 找到匹配: hello

2.2 元字符

正則表達式中具有特殊含義的字符:

  • .?匹配任意單個字符(除了換行符)

  • ^?匹配字符串的開頭

  • $?匹配字符串的結尾

  • *?匹配前面的子表達式零次或多次

  • +?匹配前面的子表達式一次或多次

  • ??匹配前面的子表達式零次或一次

  • {m,n}?匹配前面的子表達式m到n次

  • []?字符集,匹配其中任意一個字符

  • |?或操作,匹配左邊或右邊的表達式

  • ()?分組,標記一個子表達式的開始和結束位置

2.3 字符類

  • \d?匹配任意數字,等價于[0-9]

  • \D?匹配任意非數字字符

  • \s?匹配任意空白字符(空格、制表符、換行符等)

  • \S?匹配任意非空白字符

  • \w?匹配任意字母數字字符,等價于[a-zA-Z0-9_]

  • \W?匹配任意非字母數字字符

三、re模塊API詳解

3.1 re.compile(pattern, flags=0)

編譯正則表達式模式,返回一個正則表達式對象。

參數說明:

  • pattern: 要編譯的正則表達式字符串

  • flags: 可選標志,用于修改正則表達式的匹配方式

常用flags:

  • re.IGNORECASE?或?re.I: 忽略大小寫

  • re.MULTILINE?或?re.M: 多行模式,影響^和$

  • re.DOTALL?或?re.S: 使.匹配包括換行符在內的所有字符

示例:

# 編譯一個正則表達式對象
pattern = re.compile(r'\d{3}-\d{3}-\d{4}', re.IGNORECASE)# 使用編譯后的對象進行匹配
text = "我的電話號碼是123-456-7890"
match = pattern.search(text)
if match:print("找到電話號碼:", match.group())  # 輸出: 找到電話號碼: 123-456-7890

3.2 re.search(pattern, string, flags=0)

掃描整個字符串并返回第一個成功的匹配。

參數說明:

  • pattern: 要匹配的正則表達式

  • string: 要搜索的字符串

  • flags: 可選標志

示例:

text = "Python是一種流行的編程語言,Python簡單易學"
match = re.search(r'Python', text)
if match:print("找到匹配:", match.group())  # 輸出: 找到匹配: Pythonprint("匹配位置:", match.span())  # 輸出: 匹配位置: (0, 6)

3.3 re.match(pattern, string, flags=0)

嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,就返回None。

與search的區別:

  • match只在字符串開頭匹配

  • search在整個字符串中搜索第一個匹配

示例:

text1 = "Python很棒"
text2 = "學習Python很棒"print(re.match(r'Python', text1))  # 返回匹配對象
print(re.match(r'Python', text2))  # 返回None

3.4 re.findall(pattern, string, flags=0)

返回字符串中所有與模式匹配的非重疊匹配項,作為字符串列表。

示例:

text = "蘋果10元,香蕉5元,橙子8元"
prices = re.findall(r'\d+元', text)
print(prices)  # 輸出: ['10元', '5元', '8元']

3.5 re.finditer(pattern, string, flags=0)

返回一個迭代器,產生所有非重疊匹配的匹配對象。

與findall的區別:

  • findall返回字符串列表

  • finditer返回匹配對象迭代器

示例:

text = "Python 3.8, Python 3.9, Python 3.10"
matches = re.finditer(r'Python \d+\.\d+', text)
for match in matches:print(f"找到: {match.group()} 在位置 {match.span()}")
# 輸出:
# 找到: Python 3.8 在位置 (0, 9)
# 找到: Python 3.9 在位置 (11, 20)
# 找到: Python 3.10 在位置 (22, 32)

3.6 re.sub(pattern, repl, string, count=0, flags=0)

替換字符串中的匹配項。

參數說明:

  • pattern: 正則表達式模式

  • repl: 替換的字符串或函數

  • string: 原始字符串

  • count: 最大替換次數,0表示替換所有

  • flags: 可選標志

示例:

text = "今天是2023-05-15,明天是2023-05-16"
# 替換日期格式
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\1年\2月\3日', text)
print(new_text)  # 輸出: 今天是2023年05月15日,明天是2023年05月16日# 使用函數作為替換
def to_upper(match):return match.group().upper()text = "hello world"
new_text = re.sub(r'\w+', to_upper, text)
print(new_text)  # 輸出: HELLO WORLD

3.7 re.split(pattern, string, maxsplit=0, flags=0)

按照能夠匹配的子串將字符串分割后返回列表。

參數說明:

  • pattern: 分隔符正則表達式

  • string: 要分割的字符串

  • maxsplit: 最大分割次數,0表示不限制

  • flags: 可選標志

示例:

text = "蘋果,香蕉,,橙子, 西瓜"
# 按逗號分割,忽略空格和空字符串
items = re.split(r'\s*,\s*', text.strip())
print(items)  # 輸出: ['蘋果', '香蕉', '', '橙子', '西瓜']# 使用多個分隔符
text = "蘋果 香蕉,橙子;西瓜"
items = re.split(r'[ ,;]', text)
print(items)  # 輸出: ['蘋果', '香蕉', '橙子', '西瓜']

四、匹配對象的方法

當使用search()match()成功匹配后,會返回一個匹配對象,該對象有以下方法:

4.1 group([group1, ...])

返回匹配的一個或多個子組。

示例:

text = "John Doe, 30歲"
match = re.search(r'(\w+) (\w+), (\d+)歲', text)
if match:print("完整匹配:", match.group(0))  # 輸出: 完整匹配: John Doe, 30歲print("名字:", match.group(1))     # 輸出: 名字: Johnprint("姓氏:", match.group(2))     # 輸出: 姓氏: Doeprint("年齡:", match.group(3))     # 輸出: 年齡: 30print("所有組:", match.groups())   # 輸出: 所有組: ('John', 'Doe', '30')

4.2 groups(default=None)

返回一個包含所有子組的元組。

4.3 groupdict(default=None)

返回一個包含所有命名子組的字典,鍵為子組名。

4.4 start([group]) 和 end([group])

返回匹配的子組的開始和結束位置。

4.5 span([group])

返回一個元組包含匹配的子組的 (開始, 結束) 位置。

五、高級正則表達式技巧

5.1 非貪婪匹配

默認情況下,*+是貪婪的,會匹配盡可能多的字符。添加?使其變為非貪婪:

text = "<h1>標題</h1><p>段落</p>"
# 貪婪匹配
greedy = re.search(r'<.*>', text)
print(greedy.group())  # 輸出: <h1>標題</h1><p>段落</p># 非貪婪匹配
non_greedy = re.search(r'<.*?>', text)
print(non_greedy.group())  # 輸出: <h1>

5.2 前向斷言和后向斷言

  • (?=...)?正向前視斷言

  • (?!...)?負向前視斷言

  • (?<=...)?正向后視斷言

  • (?<!...)?負向后視斷言

示例:

# 匹配后面跟著"元"的數字
text = "蘋果10元,香蕉5元,橙子8個"
prices = re.findall(r'\d+(?=元)', text)
print(prices)  # 輸出: ['10', '5']# 匹配前面是"價格:"的數字
text = "價格:100,數量:5"
numbers = re.findall(r'(?<=價格:)\d+', text)
print(numbers)  # 輸出: ['100']

5.3 命名組

使用(?P<name>...)語法為組命名:

text = "2023-05-15"
match = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', text)
if match:print(match.groupdict())  # 輸出: {'year': '2023', 'month': '05', 'day': '15'}

5.4 條件匹配

使用(?(id/name)yes-pattern|no-pattern)

# 如果第一個組匹配"Mr",則匹配"Smith",否則匹配"Smithson"
text1 = "Mr Smith"
text2 = "Mrs Smithson"
pattern = r'(Mr)? (?(1)Smith|Smithson)'print(re.match(pattern, text1))  # 匹配
print(re.match(pattern, text2))  # 匹配

六、實際應用示例

6.1 驗證電子郵件地址

def validate_email(email):pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'return re.match(pattern, email) is not Noneprint(validate_email("test@example.com"))  # True
print(validate_email("invalid.email@"))    # False

6.2 提取URL信息?

def extract_url_info(url):pattern = r'(https?)://([^/]+)(/.*)?'match = re.match(pattern, url)if match:return {'protocol': match.group(1),'domain': match.group(2),'path': match.group(3) or '/'}return Noneurl_info = extract_url_info("https://www.example.com/path/to/page")
print(url_info)
# 輸出: {'protocol': 'https', 'domain': 'www.example.com', 'path': '/path/to/page'}

6.3 日志分析?

log_line = '127.0.0.1 - - [10/May/2023:15:32:45 +0800] "GET /index.html HTTP/1.1" 200 1234'pattern = r'^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) (\S+)" (\d+) (\d+)'
match = re.match(pattern, log_line)if match:log_data = {'ip': match.group(1),'time': match.group(2),'method': match.group(3),'path': match.group(4),'protocol': match.group(5),'status': int(match.group(6)),'size': int(match.group(7))}print(log_data)# 輸出: {'ip': '127.0.0.1', 'time': '10/May/2023:15:32:45 +0800', # 'method': 'GET', 'path': '/index.html', 'protocol': 'HTTP/1.1',# 'status': 200, 'size': 1234}

七、性能優化建議

  1. 預編譯正則表達式:對于重復使用的正則表達式,使用re.compile()預先編譯。

  2. 使用非貪婪匹配:當可能時,使用非貪婪限定符*?+?等。

  3. 避免回溯災難:復雜的正則表達式可能導致性能問題,盡量簡化。

  4. 使用原子組(?>...)可以防止回溯。

  5. 合理使用字符類[abc](a|b|c)更高效。

八、常見問題與解決方案

8.1 匹配多行文本

使用re.MULTILINE標志:

text = """第一行
第二行
第三行"""
matches = re.findall(r'^第\w+', text, re.MULTILINE)
print(matches)  # 輸出: ['第一行', '第二行', '第三行']

8.2 忽略大小寫匹配

使用re.IGNORECASE標志:

text = "Python python PYTHON"
matches = re.findall(r'python', text, re.IGNORECASE)
print(matches)  # 輸出: ['Python', 'python', 'PYTHON']

8.3 匹配Unicode字符

使用\u\x轉義,或直接包含Unicode字符:

text = "中文Chinese にほんご"
matches = re.findall(r'[\u4e00-\u9fa5]+', text)  # 匹配中文字符
print(matches)  # 輸出: ['中文']

九、總結

Python的正則表達式功能強大而靈活,re模塊提供了豐富的API來處理各種文本匹配需求。掌握正則表達式可以大大提高文本處理的效率和能力。記住:

  1. 復雜的正則表達式可以先分解為多個簡單的部分

  2. 使用re.VERBOSE標志可以使復雜的正則表達式更易讀

  3. 測試正則表達式時可以使用在線工具如regex101.com

  4. 對于非常復雜的文本處理,可能需要結合其他方法(如解析器)

希望本博客能幫助你掌握Python正則表達式的使用!

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87959.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87959.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87959.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

pytest合并allure報告解決方案

背景 在執行自動化測試的過程中&#xff0c;為了實現自動化的高通過率&#xff0c;可能會反復的重試&#xff0c;直至大多數甚至全部用例執行通過&#xff0c;以此來需要人為分析的用例量&#xff0c;減少人力投入&#xff0c;提高執行效率&#xff1b; 在用例少或者資源消耗小…

Pr插件圖文安裝教程

Pr插件圖文安裝教程 Adobe Premiere Pro&#xff0c;簡稱Pr&#xff0c;是由Adobe公司開發的一款視頻編輯軟件。Adobe Premiere有較好的兼容性&#xff0c;且可以與Adobe公司推出的其他軟件相互協作。這款軟件廣泛應用于廣告制作和電視節目制作中&#xff0c;是視頻編輯愛好者…

[netty5: HttpObjectEncoder HttpObjectDecoder]-源碼解析

在閱讀該篇文章之前&#xff0c;推薦先閱讀以下內容&#xff1a; [netty5: HttpObject]-源碼解析[netty5: MessageToMessageCodec & MessageToMessageEncoder & MessageToMessageDecoder]-源碼分析[netty5: ByteToMessageCodec & MessageToByteEncoder & Byte…

uniapp的navigator跳轉功能

接下來&#xff0c;我將圍繞一個常見的電商小程序來構建一系列連貫的使用場景。在這個過程中&#xff0c;我們將把 <navigator> 組件的所有關鍵屬性和方法都串聯起來&#xff0c;并詳細解釋它們在每個環節所扮演的角色和作用。 核心場景&#xff1a;構建一個電商小程序的…

v-for的用法及案例

目錄 一.v-for的用法 1.舉例1 2.舉例2 二.購物車案例 1.代碼 2.存在的問題&#xff1a;復選框錯位 3.解決方案&#xff1a; 賦值給key屬性一個唯一的值 一.v-for的用法 1.舉例1 <template><view><view v-for"(item,index) in 10" :key"…

BigQuery對象引用(ObjectRef)全面指南:一站式整合結構化與非結構化多模態數據分析

引言 企業需要同時管理有組織表格中的結構化數據&#xff0c;以及日益增長的非結構化數據&#xff08;如圖片、音頻和文檔&#xff09;。傳統上&#xff0c;聯合分析這些多樣化數據類型非常復雜&#xff0c;通常需要使用不同的工具。非結構化媒體通常需要導出到專門的服務進行…

【開源品鑒】FRP源碼閱讀

frp 是一款高性能的反向代理應用&#xff0c;專注于內網穿透&#xff0c;支持多種協議和 P2P 通信功能&#xff0c;目前在 GitHub 上已有 80k 的 star。本文將深入探討其源碼&#xff0c;揭示其背后的實現原理。1. 前言 frp 是一款高性能的反向代理應用&#xff0c;專注于內網…

day048-系統負載高排查流程與前后端分離項目

文章目錄 0. 老男孩思想1. 系統負載高排查流程1.1 進程/線程相關命令1.1.1 jps1.1.2 jstack1.1.3 jmap1.1.4 top -Hp pid 1.2 排查流程圖 2. 前后端分離項目2.1 項目說明2.2 負載均衡2.3 數據庫配置2.3.1 安裝數據庫服務2.3.2 配置數據庫環境 2.4 后端配置2.5 四層負載均衡配置…

Spring Boot 牽手EasyExcel:解鎖高效數據處理姿勢

引言 在日常的 Java 開發中&#xff0c;處理 Excel 文件是一個極為常見的需求。無論是數據的導入導出&#xff0c;還是報表的生成&#xff0c;Excel 都扮演著重要的角色。例如&#xff0c;在企業的財務管理系統中&#xff0c;需要將每月的財務數據導出為 Excel 報表&#xff0…

【ARM AMBA AXI 入門 21 -- AXI partial 訪問和 narrow 訪問的區別】

文章目錄 Overview一、定義區別二、AXI 信號層面對比三、舉例說明示例一:Partial Access示例二:Narrow Access四、硬件/系統處理角度五、AXI 總線接口信號舉例對比Partial Write 事務:Narrow Write 事務(32-bit Master on 64-bit Bus):六、總結對比表七,軟件判斷判斷 Pa…

使用Ideal創建一個spring boot的helloWorld項目

說明&#xff1a;本篇將介紹如何使用Ideal2024.2.1去創建一個spring boot的helloWorld項目&#xff0c;本篇將包含創建的詳細步驟以及spring boot項目的目錄結構說明&#xff0c;創建過程中的選項說明等。詳細步驟如下&#xff1a;第一步&#xff1a;點擊文件——新建——項目&…

國內Ubuntu訪問不了github等外網

各位小伙伴們&#xff0c;大家好呀。 大家是不是經常遇到訪問不了外網的情況呀。 在Ubuntu中可以這樣做。 訪問這個網站網站測速-Ping檢測-Trace查詢-Dig查詢-路由跟蹤查詢-tools.ipip.net&#xff0c; 對于github.com&#xff0c;在這個網站輸入github.com&#xff0c;會返…

PDF轉換工具,即開即用

在辦公室里&#xff0c;這句話被反復驗證。每天面對成堆的Word和Excel文件&#xff0c;將它們轉換成PDF格式是常有的事。可之前用過的工具&#xff0c;不是一次只能轉一個&#xff0c;就是操作繁瑣得讓人頭疼。記得有次趕項目&#xff0c;需要把二十多個文檔轉成PDF&#xff0c…

2. 你可以說一下 http 版本的發展過程嗎

你可以說一下 http 版本的發展過程嗎 總結&#xff1a;0.9&#xff1a;只能發送 get&#xff0c;無狀態。1.0&#xff1a;新增 post&#xff0c;請求頭&#xff0c;狀態碼&#xff0c;cookie。1.1&#xff1a;新增 put/delete/options/patch&#xff0c;keep-alive&#xff0c…

04-Linux驅動模塊的自動加載

概述 上一節&#xff0c;我們講述了Linux驅動開發的基本的模塊代碼編寫和手動執行模塊加載的操作&#xff0c; 這一節&#xff0c;我們講述嵌入式設備上使用Sysvint引導方式下如何開機自動加載模塊的步驟。感興趣的同學看下使用systemd引導方式的開啟自動加載模塊的步驟 操作…

【牛客算法】游游的整數切割

文章目錄 一、題目介紹1.1 題目鏈接1.2 題目描述1.3 輸入描述1.4 輸出描述1.5 示例二、解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:基礎遍歷法3.1.1 初級版本分析3.2 解法二:奇偶預統計法(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關…

筆記本電腦忽亮忽暗問題

關于筆記本電腦忽亮忽暗的問題這個問題困擾了我大半年&#xff0c;最后忽然找到解決方法了---主要的話有三種可能性1.關閉顯示器自動調亮的功能2.關閉節能模式自動調亮功能3.調整顯卡的功率&#xff0c;關閉自動調亮功能一開始一直都是嘗試的第一種方法&#xff0c;沒解決。。。…

Qt的頂部工具欄在多個界面使用

Qt的工具欄在多個界面使用1、前言2、創建一個工具欄類2.1 新建一個工具欄類3、提升工具欄類3.1登錄界面添加工具欄3.2 創建工具欄對象4、總結1、前言 今天遇到了個問題&#xff0c;頂部的工具欄&#xff0c;像軟鍵盤&#xff0c;時間顯示和退出按鈕那些&#xff0c;想在多個界…

C#和SQL Server連接常用通訊方式

C#和SQL Server連接通訊 在 C# 中與 SQL Server 建立數據庫連接&#xff0c;主要通過 ADO.NET 技術實現。以下是幾種常見的連接方式及相關實踐&#xff1a; ADO.NET 全面指南&#xff1a;C# 數據庫訪問核心技術 ADO.NET 是 .NET Framework 中用于數據訪問的核心組件&#xf…

安卓10.0系統修改定制化____實現自動開啟 USB 調試?的步驟解析 列舉常用的幾種修改方法

對于安卓開發者、測試人員,甚至是喜歡折騰手機的數碼愛好者來說,USB 調試是一個非常重要的功能。它能讓手機與電腦相連,實現應用安裝、系統調試、數據傳輸等操作。但每次連接手機都要手動去設置里開啟 USB 調試,實在麻煩。其實,通過修改安卓 10.0 的 ROM,就能讓手機自動開…