2026年5月31日

我在 perl 工作 30 年,現在學習 python 所以比較一下


三十年的 Perl 資歷是非常深厚的底蘊!Perl 作為文字處理的文字堂級語言,其正規表達式(Regex)已經深入到語言的骨髓裡(語法糖非常甜);而 Python 則是將其收納在內建的 re 模組中。
為了讓您能將三十年的 Perl 功力無縫平移到 Python,我幫您整理了一份 Perl vs Python Regex 核心語法對照表

一、 核心操作對照表
在 Python 中,所有 Regex 操作都要先 import re
功能Perl 語法Python (re 模組) 語法說明
匹配檢查$text =~ /pattern/if re.search(r'pattern', text):re.search 會搜尋整段字串。
錨定開頭$text =~ /^pattern/re.match(r'pattern', text)Python 的 match 強迫從字串開頭算起。
全域取代$text =~ s/patt/repl/g;text = re.sub(r'patt', 'repl', text)Python 預設就是全域取代(/g)。
單次取代$text =~ s/patt/repl/;text = re.sub(r'patt', 'repl', text, count=1)Python 需指定 count=1
取得次數my $count = ($text =~ s/patt/repl/g);text, count = re.subn(r'patt', 'repl', text)re.subn 會回傳一個包含次數的 Tuple。

二、 旗標(Modifiers / Flags)對照
Perl 習慣把旗標放在結尾(例如 /ixsm),Python 則是作為參數傳入(例如 re.I)。
Perl 旗標Python 旗標功能說明
/ire.IGNORECASE (或 re.I)忽略大小寫
/sre.DOTALL (或 re.S)讓句點 . 可以匹配換行符 \n
/mre.MULTILINE (或 re.M)^$ 匹配每一行的開頭與結尾
/xre.VERBOSE (或 re.X)忽略空白與支援 # 註解(撰寫複雜 Regex 必備)
Python 範例:
python
# 同時使用多個旗標,用管線符號 | 連結
result = re.sub(r'apple', 'orange', text, flags=re.I | re.M)
請謹慎使用程式碼。

三、 您需要適應的 3 個 Python 盲點(Perl 視角)
1. 捕獲群組(Capture Groups)的變數
  • Perl:匹配成功後,直接用 $1, $2 拿資料。
  • Python:必須先取得一個 Match 物件,再透過 .group(1) 提取。
python
# Python 寫法
match = re.search(r'(\d{4})-(\d{2})', "2026-05")
if match:
    year = match.group(1)   # 相當於 Perl 的 $1
    month = match.group(2)  # 相當於 Perl 的 $2
請謹慎使用程式碼。
2. 沒有內建的 \G 錨點與部分進階功能
Python 的 re 模組實作的是比較傳統的 POSIX/PCRE 概念,Perl 5.10+ 以後很多超強大的特性(例如 (?{ code }) 內嵌程式碼、\G 續接錨點)在 Python 內建的 re不支援的。
前輩敲黑板 💡:如果您在 Python 專案中發現內建 re 不夠用,社群上有一個第三方庫叫 regex,它支援完整的 Perl 風格特性(包含變長逆向斷言等),可以用 pip install regex 安裝並完全取代 re
3. 字串不可變性(Immutable)
  • Perl$text =~ s/.../.../直接修改 $text 變數本身。
  • Python:字串是不可變的,re.sub() 永遠只會回傳一個新字串,您必須自己接住它:text = re.sub(...)
以您的深厚功力,只要習慣 Python 將 Regex「物件、函數化」的風格,基本上心法都是完全通用的。您可以參考 Python 官方的正規表達式指引,裡面甚至有一小段專門寫給 Perl 轉過來的開發者看。
您以前在 Perl 最常處理哪一類的文字任務(例如:大型日誌 (Logs) 解析ETL 資料清理、或是網頁爬蟲)?您可以拿一個您以前寫過最自豪(或最複雜)的 Perl Regex 一行文 (One-liner),我們一起把它翻成優雅的 Python 程式碼!

沒有留言: