正規表示式
re是 Regular Expression 的縮寫. 中文稱為正規表示式. 是一種用特定符號來表示字串內容要求的格式.
比如輸入一組電話號碼, “0987-就北七-就北七”, 顯然這不是電話號碼.
而 “0987-9879-87” 這組顯然是電話號碼, 但分隔文字 “-” 出現的位置怪怪的, 所以也不符合我們要求的格式.
“我希望這字串裏所有的字都是數字, 然後前四碼要加 ‘-‘, 接下來每三碼就加 ‘-‘ “, 比如 “0987-987-987” 那就符合上面藍色字的要求.
藍色部份, 是用我們熟悉的語言表達出來. 電腦當然看不懂, 所以我們就要發明一種電腦可以看懂的表達方式, 這種方式就叫正規表示式.
re模組
電腦可以看得懂的表達方式, 這句話好像很正常, 但仔細想一想, 電腦只看得懂 0 跟 1 啊. 所以就必需再撰寫一個函數, 用來解析這種表達方式. Python使用re模組來解析正規表示式. 所以嚴格來說, 正規表示式是用來讓 re模組看得懂的表達方式.
下面的pattern, 就是樣板、樣式的意思, 裏面的符號都是正規表示式. re.match(pattern, 字串) 會將字串進行核對, 是否符合pattern的要求. 若符合就會傳回一個Match物件, 否則就傳回None
import re
pattern="\d\d\d\d-\d\d\d-\d\d\d"
if re.match(pattern, '0987-987-987'):
print("It's a phone number")
else:
print("wrong number")
pattern裏那串很胎哥(骯髒)的符號, 到底是啥意思. 這就很讓人頭大了, 因為要背起來, 偏偏本人怎麼背也背不起來, 所以只好寫這篇文章方便日後查詢用.
跳脫, 轉譯字元
在Python字串中常看到 “\n” , 這種 “\”叫跳脫字元. 那如果想要純粹是 “\”的一般字元呢, 那就要使用 “\\”.
然而在正規表示式中, “\”又是另一種轉譯字元, 所以在pattern中若要表達 “\”, 就要使用 “\\\\”. 因此為了省麻煩, 就會在字串前加一個 “r”, 宣告不要把 “\”當成轉譯字元. 所以pattern就可以寫成 “\\”. 如下
import re pattern1=r"\d\d\d\d\\\d\d\d\-\d\d\d" #只需二個 \\ pattern2="\d\d\d\d\\\\\d\d\d\-\d\d\d" #需四個 \\\\
單一字表示式
\d : 一個數字. 如’00\d’, ‘007’符合(match), ’00A’不符合
\w : 一個字母或數字. 如’00\w’, ‘007’及 ’00a’都符合
\s : 一個空格或Tab
. : 任何字元都符合, 包含了符號及空格
長度表示式
* : 任意個字元
+ : 至少1個字元
? : 0 或1 個字元
{n} : n 個字元
{n, m} : n-m個字元
\d{3}\s+\d{2,5} : 如 “123 45678 幾個空格都可以
\d{4}-\d{3}-\d{3} : “0987-987-987”
範圍表示式
[0-9a-zA-z\_] : 一個數字或一個字母或底線
[0-9a-zA-z\_]+ : 至少(一個數字或一個字母或底線), 如 “a12-4567abc”
[a-zA-z\_][0-9]{9} : 開頭必需是字母, 後面9 個數字. 這就是台灣身份証的表示式
頭尾表示式
^ : 行開頭. ^\d, 開頭必需是數字
$ : 行結尾. \d$, 結尾必需是數字
re函數
re.match(pattern, ‘字串’) : 若有批配, 傳回Match物件, 否則傳回None
re.findall(pattern, ‘字串’) : 傳回3個數字連在一起的list
pattern1=r"\d{3}" print(re.findall(pattern1, "abc12345678a")) 結果 : ['123', '456']
re.split(pattern, ‘字串’) : 切割
pattern1=r"[\s\,]+" print(re.split(pattern1, "abc 123,,456 78a")) 結果 : ['abc', '123', '456', '78a']
分組
re.match()可以加入 “()” 進行分組, 使用m.group()取出. group(0)是原始字串
m = re.match(r'^(\d{4})-(\d{3,8})-(\d{3})', '0987-987-766') print(m.group(0)) print(m.group(1)) print(m.group(2)) print(m.group(3))
compile
運算正規表示式時, 會先將pattern進行編譯, 然後才批配. 如果同一個表示式要批配1000個字串, 那就要編譯1000次, 再批配1000次, 電腦不煩我們看了也煩.
所以可以先編譯一次, 再利用編譯後的物件進行批配. 利用編譯後的物件批配時, 就不需再傳入pattern了.
pattern1=r"[\s\,]+" rc=re.compile((pattern1)) r=rc.split("abc 123,,456 78a") print(r)