You are on page 1of 40

第 16 章

正則表達式 Regular Expression


16-1 :使用 Python 直接搜尋文字
• 台灣的手機號碼格式: 09XX-XXX-XXX
 12 字元,第 5, 9 字元為 “ -” ,其
他字元為 0~9 的數字

• 若要從一段字串中找出手機號碼:
1. 每 12 個字元進行一次搜尋是否滿足手機格
式?
2. 檢查第 5 與 9 字元是否為 “ -” ,其他字
元是否為 0~9 的數字?

• 需重複比對!
16-2 :正則表達式的基礎
• 正則表達式 (Regular Expression)
 執行模式比對與搜尋
 import re # 導入 re 模組

• 正則表達式是文字模式的表達方法
使用 \d 表示 0-9 的數字字元,手機號碼:
‘\d\d\d\d-\d\d\d-\d\d\d’
因為逸出字元:
‘\\d\\d\\d\\d-\\d\\d\\d-\\d\\d\\d’
(3-4-9 節 ) 字串加 r 防止逸出字元被轉譯:
r‘\d\d\d\d-\d\d\d-\d\d\d’
16-2-2 :使用 re.compile() 建立 Regex
物件
16-2-3 :搜尋物件
• Regex 物件
 Re 模組內有 compile() 方法回傳 Regex 物件,參數為欲搜尋字串的正則表
達式,例如:
phoneRule = re.compile(r’\d\d\d\d-\d\d\d-\d\d\d’)
# 建立 phoneRule 物件
 Regex 物件有 search() 方法可以搜尋是否有符合設定的正則表達式,例如:
phoneNum = phoneRule.search(msg)
# msg 是欲搜尋的字串
 若無符合字串回傳 None
 MatchObject 物件
 只回傳第一個比對符合的字串
 用 group() 方法回傳 MatchObject 物件的內容
16-2-3 :搜尋物件

• 程式實例 ch16_3.py :使用正則表達


式重新設計 ch16_2.py
16-2-4 : findall( )

• 程式實例 ch16_4.py :使用 findall() 重


新設計 ch16_3.py 搜尋字串
會以串列回傳所有符合的字串
若無則回傳空串列
可直接使用 phoneNum
16-2-5 :再看 re 模組
16-2-6 :再看正則表達式
• Re.compile() 可以省略,對應的 search() 與 findall() 語法為:
re.search(pattern, string, flags)
re.findall(pattern, string, flags)
pattern: 欲搜尋的正則表達式
string: 欲搜尋的字串
flags: 額外的參數

• 重複出現可以用大括號加上次數表達,所以手機號碼的正則表達式可以簡化為:
r‘\d{4}-\d{3}-\d{3}’
16-2-5 :再看 re 模組
16-2-6 :再看正則表達式
• 程 式 實 例 ch16_6.py : 省 略
re.compile() 並使用 re.findall() 重新設
計 ch16_4.py
16-3 :更多搜尋比對模式
• 台北市電話號碼: 02-28350000
台北市電話號碼的正則表達式: r‘\d\d-\d\d\d\d\d\d\d\d’

• 使用小括號分組
以 ” -” 區別,用小括號隔開群組,台北市電話號碼的正則表達式:
r‘(\d{2})-(\d{8})’

• 使用 re.search() 比對
未來可以使用 group() 傳回比對符合的不同分組,
例如: group() 或 group(0) 傳回第一個符合的文字與 ch16_3.py 觀念相同。
如果 group(1) 則傳回括號的第一組文字, group(2) 則傳回括號的第二組文字
• 程 式 實 例 ch16_8.py : 使 用 小 括 號 分 組 的 觀 念 , 分 別 使 用
search() 與 findall() 搜尋並將內容輸出
16-3-2 : groups( )

• 以 re.search() 搜尋字串,可使用
groups() 取得分組的內容
注意: groups()
使用多重指定:
areaNum, localNum = phoneNum.groups( )

• 程 式 實 例 ch16_10.py : 針 對 re.search()
的部分重新設計 ch16_8.py ,分別列出區
域號碼與電話號碼
16-3-3 :區域號碼在小括號內
• 區域號碼用小括號: (02)-26669999
處理方式: \( 和 \)
例如: pattern = r”(\(\d{2}\))-(\d{8})”
16-3-4 :使用管道 (pipe) |

• 使用管道可同時搜尋比對多個字串
想同時搜尋 Mary 和 Tom:
pattern = ‘Mary|Tom’
# ’ 或 | 旁不可留空白

• 程式實例 ch16_12.py :管道搜尋多個字


串的實例
16-3-5 :多個分組的管道搜尋

• 假設字串如下:
“Johnson, Johnnason and Johnnathan will
attend my party tonight.”
若 搜 尋 John 後 面 允 許
son 、 nason 、 nathan ,可以使用
下列正則表達式:
pattern = ‘John(son|nason|nathan)’

• 程式實例 ch16_13.py :搜尋 Johnson,


Johnnason 或 Johnnathan 任一字串,
然後列出結果
16-3-6 :使用 ? 搜尋

• 若允許某些括號內字串或正則表達式是
可有可無 ,例如: na 字串可有可無,
表達方式為 (na)?

• 程式實例 ch16_15.py :使用 ? 搜尋的實



• 程式實例 ch16_16.py :這個程式
在搜尋電話號碼時,如果省略區
域號碼程式也可以搜尋到此號碼,
然後列印出來
16-3-7 :使用 * 做搜尋

• 若允許某些字串或正則表達式出現 0
到多次,例如: na 字串可出現 0 到
多次,表達方式為 (na)*

• 程式實例 ch16_17.py :這個程式的重


點是正則表達式,其中字串 na 的出
現次數可以是從 0 次到多次
16-3-8 :使用 + 做搜尋

• 若允許某些字串或正則表達式出現 1
到多次,例如: na 字串可出現 1 到
多次,表達方式為 (na)+

• 程式實例 ch16_18.py :這個程式的重點


是正則表達式,其中字串 na 的出現次
數可以是從 1 次到多次
16-3-9 :搜尋時忽略大小寫

• 在 search() 或 findall() 增加第三個參


數 re.I 或 re.IGNORECASE ,搜尋時會
忽略大小寫,列印時將以原字串的格式
顯示

• 程式實例 ch16_19.py :以忽略大小寫方


式執行找尋相符字串
16-4 :貪婪與非貪婪搜尋
16-4-1 :搜尋時使用大括號設定比對次數
• 大括號
設定重複次數
設定指定範圍,例如:
 (son){3,5} 代表所搜尋的字串如果是 ‘ sonsonson’(3 次 ) 、’ sonsonsonson’ (4 次 ) 或
’ sonsonsonsonson’ (5 次 ) 皆符合
 (son){3,5} 等價 ((son)(son)(son))|((son)(son)(son)(son))|((son)(son)(son)(son)(son))
(son){3,}: 重複 3 次以上皆符合, (son){,5}: 重複 5 次以下皆符合
注意:設定 ’ (son){3,5}’ 時,’ sonsonsonsonsonson’ (6 次 ) 也算符合!
• 程式實例 ch16_20.py :設定搜尋
son 字串重複 3-5 次皆算搜尋成

 msg2, msg3, msg4 都是搜尋到允許範
圍內最多次的結果 ( 貪婪搜尋 )
 若要列出最少重複字串 ( 非貪婪搜
尋 ) ,則須在正則表達式最右邊加入
“ ?” ,例如:‘ (son){3,5}?’
16-5 :正則表達式的特殊字元

• 例如:
1. \d+: 不限長度的數字
2. \w+: 表示不限長度的數字、字母和底線字元連續字元
• 程式實例 ch16_23.py :將一段英文句子的單字分離,同時將英文
單字前 4 個字母是 John 的單字分離。設定如下:
16-5-2 :字元分類
• Python 可以使用中括號來設定字元,範例:
 [a-z]: a-z 小寫字元
 [A-Z]: A-Z 大寫字元
 [aeiouAEIOU]: 英文母音字元
 [2-5]: 2-5 數字

• 中括號內可以不用正則表達式的 \ 執行,” .?*()” 等字元的轉譯,範例:


 [2-5.]: 2-5 的數字與句點,不用寫成 [2-5\.]

• 程式實例 ch16_25.py :搜尋字元的應用,這個程式首先搜尋 [aeiouAEIOU] ,然後


搜尋 [2-5.]
16-5-3 :字元分類的 ^ 字元
• 中括號內最左邊加入 ^ 則會搜尋不在設定字元的所有內容 ( 補集 )

• 程式實例 ch16_26.py :使用字元分類的 ^ 字元重新設計 ch16_25.py


16-5-4 :正則表示法的 ^ 字元
• 正則表示最左邊加入 ^ :字串必須出
現在被搜尋單字的起始才算搜尋成功

• 程式實例 ch16_27.py :正則表示法 ^


字元的應用,測試 1 字串 John 是在最
前面所以可以得到搜尋結果,測試 2
字串 John 不是在最前面,結果搜尋失敗
傳回空字串。
16-5-5 :正則表示法的 $ 字元
• 正則表示最右邊加入 $ :字串必須出
現在被搜尋單字的最後才算搜尋成功

• 程式實例 ch16_29.py :搜尋開始到結束


皆是數字的字串,字串內容只要有非數
字字元就算搜尋失敗。測試 2 中由於
中間有非數字字元,所以搜尋失敗
16-5-6 :單一字元使用萬用字元 ” .”
16-5-7 :所有字元使用萬用字元 ” .*”
• 萬用字元 (wildcard) “.” 可以搜尋除了換行字元以外的所有字元
只能一個字元
若要搜尋多個萬用字元,需使用 “ .*”
若要搜尋的是句號字元,需使用 “ \.”

• 程式實例 ch16_30.py :萬用字元的應用,搜尋一個萬用字元加上 at ,在下列輸出


中第 4 筆,由於 at 符合, Python 自動加上空白字元。第 6 筆由於只能加上一個字
元,所以搜尋結果是 lat 。

• 程式實例 ch16_31.py :搜尋所有字元 “ .*” 的組合應用。


16-5-8 :換行字元的處理
• 程式實例 ch16_32.py :測試 1 是搜尋換行字元以外的字元,測試 2 是搜尋含換行字
元的所有字元。由於測試 2 有包含換行字元,所以輸出時,換行字元主導分 2 行輸

16-6 : MatchObject 物件
• re.match()
re.search() 搜尋整個比對字串,
成功會產生 MatchObject 物件
re.match() 搜尋比對字串開始的
字,成功會產生 MatchObject
物件

• 程 式 實 例 ch16_33.py : re.match()
的應用。測試 1 將 John 放在被搜
尋字串的最前面,測試 2 沒有將
John 放在被搜尋字串的最前面
re.search() 或 re.match() 搜尋成
功會產生 MatchOjbect 物件
16-6-2 : MatchObject 幾個重要的方法
16-7 :搶救 CIA 情報員 -sub() 方法
• re 模組的 sub() 方法:用新的字串
取代原本字串
result = re.sub(pattern, newstr, msg)
# msg 欲處理的字串
pattern: 欲搜尋的字串
newstr: 搜尋成功則用 newstr
取代並回傳給 result (msg 不會
被更改! )
msg: 被搜尋的字串

• r”CIA (\w)\w*”: CIA + 半形空格 + 一個數字、


• 程式實例 ch16_37.py :將 CIA 情報 字母或底線 + 0- 多個數字、字母或底線
員名字,用名字第一個字母和 ***  當中有一組 (\w)
取代
• r”\1***”: 針對第一組的內容後面加上 ***
16-8 :將正則表達式拆成多行字串

• 在正則表達式中加入註解:
 pattern 中加註解沒有問題
 search(), findall(), compile() 執行時註解會有影響
 需加入參數 re.VERBOSE
16-8-2 : re.VERBOSE
• 程式實例 ch16_38.py :搜尋市區
電話號碼的應用,這個程式可以
搜尋下列格式:
 12345678 # 沒有區域碼
 02 12345678 # 區域碼與電
話使用空格分隔
 02-12345678 # 區域號碼與
電話使用 - 分隔
 (02)-12345678# 區域碼有小
括號
 02-12345678 ext 123 # 分機
 02-12345678 ext. 123 # 分機
ext 右邊有 .
16-8-3 :電子郵件地址的搜尋
• 程式實例 ch16_39.py :電子郵件地址
搜尋
 [a-zA-Z0-9_.] # 使用者
帳號常用的字元
@ # @ 符號
 [a-zA-Z0-9_.] # 主機域

 [\.] # . 符號
 [a-zA-Z0-9_.]{2,4} # com,
edu 或其他
 [\.] ? # . 符號,也
可能無 ( 特別是美國 )
 [a-zA-Z0-9_.]? # 國別
16-8-4 : re.IGNORECASE/re.DOTALL/re.VERBOSE

• 若想一次放置多個參數特性,可以使用 16-3-4 管道觀念,例如:

You might also like