1. 程式人生 > >day 18 - 1 正則與 re 模組

day 18 - 1 正則與 re 模組

正則表示式

官方定義:正則表示式是對字串操作的一種邏輯公式,就是用事先定義好的一些特定字元、及這些特定字元的組合,組成一個 “規則字串”,這個 “規則字串” 用來表達對字串的一種過濾邏輯。

我們先來看一個正則與 re 模組的例子

判斷手機號是否合法

#while 實現
while True:
    phone_number = input('please input your phone number : ')
    if len(phone_number) == 11 \
            and phone_number.isdigit()\
            
and (phone_number.startswith('13') \ or phone_number.startswith('14') \ or phone_number.startswith('15') \ or phone_number.startswith('18')): print('是合法的手機號碼') else: print('不是合法的手機號碼')
#re 模組實現
import re
phone_number = input('please input your phone number : 
') if re.match('^(13|14|15|18)[0-9]{9}$',phone_number): print('是合法的手機號碼') else: print('不是合法的手機號碼')

 

字元組

用法:[字元組]

在同一個位置可能出現的各種字元組成了一個字元組,在正則表示式中用 [] 表示
字元分為很多類,比如數字、字母、標點等等。
假如你現在要求一個位置 " 只能出現一個數字 ",那麼這個位置上的字元只能是 0、1、2...9 這 10 個數之一。

字元

元字元 匹配內容
匹配除換行符以外的任意字元
\w 匹配字母或數字或下劃線 (word)
\s 匹配任意的空白符 (space)
\d 匹配數字 (digit)
\n 匹配一個換行符 
\t 匹配一個製表符 
\b 匹配一個單詞的結尾
^ 匹配字串的開始 
$ 匹配字串的結尾 
\W 匹配非字母或數字或下劃線
\D 匹配非數字
\S 匹配非空白符
a|b 匹配字元a或字元b
() 匹配括號內的表示式,也表示一個組
[...] 匹配字元組中的字元
[^...] 匹配除了字元組中字元的所有字元



















 

量詞

量詞 用法說明
* 重複零次或更多次
+ 重複一次或更多次 
? 重複零次或一次
{n} 重複n次
{n,} 重複n次或更多次
{n,m} 重複n到m次 








.*? 的用法

 

關鍵字元 用法說明
. 是任意字元
* 是取 0 至 無限長度
? 非貪婪模式






合在一起就是 取儘量少 的任意字元,一般不會這麼單獨寫,他大多用在:(.*?x)取前面任意長度的字元,直到一個x出現的時候

其他重要的字元

字元 用法說明
\ 轉義符
{...} {1,2}匹配 1 到 2 次任意字元




貪婪匹配

貪婪格式 用法說明
<.*> 預設為貪婪匹配模式,會匹配儘量長的字串
<.*?> 加上 ?為將貪婪匹配模式轉為非貪婪匹配模式,會匹配儘量短的字串






幾個常用的非貪婪匹配(Pattern)

格式 用法
*? 重複任意次,但儘可能少重複
+? 重複1次或更多次,但儘可能少重複
?? 重複0次或1次,但儘可能少重複
{n,m}?  重複n到m次,但儘可能少重複
{n,}? 重複n次以上,但儘可能少重複








模組

re 模組

三個非常重要的方法:findall、search、match

findall(找所有)
返回所有滿足匹配條件的結果,放在列表裡

#findall
ret = re.findall('a','eva egon yuan') 
print(ret)

ret = re.findall('[a-z]+','eva egon yuan') 
print(ret)

 

search(找一個)
從前往後,找到一個就返回,返回的變數需要呼叫 group 才能拿到結果
如果沒有找到,那麼返回 None,呼叫 group 會報錯

#search
ret = re.search('a', 'eva egon yuan').group() #當不使用 group() 呼叫時,返回的是一個結果的物件
print(ret)

ret = re.search('a', 'eva egon yuan')
print(ret)

#沒有找到值  會報錯
ret = re.search('j', 'eva egon yuan').group()
print(ret)

#search 的一般用法
ret = re.search('a', 'eva egon yuan')
if ret:
    print(ret.group())
#search 結合分組的用法
ret = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$','110105199912122277')
print(ret.group())
print(ret.group(1))    #取出第一組
print(ret.group(2))    #取出第二組

 

match(從頭開始找一個) 用法 search 基本一致
match是從頭開始匹配,如果正則規則從頭開始可以匹配上,就返回一個變數。
匹配的內容需要用 group 才能顯示,如果沒匹配上,就返回 None,呼叫 group 時會報錯

#match
ret = re.match('a','eva egon,yuan') #沒有匹配到
if ret:
    print(ret.group())

ret = re.match('e','eva egon,yuan') #匹配到了
if ret:
    print(ret.group())

ret = re.match('[a-z]','eva egon,yuan') #匹配到了
if ret:
    print(ret.group())

 

其他重要的方法

方法:split、sub、subn、compile、finditer、split、flags

split
先按 'a' 分割得到 '' 和 'bcd',在對 '' 和 'bcd' 分別按 'b' 分割

#split
ret = re.split('[ab]','abcd')
print(ret)      # ['', '', 'cd']

 

sub
將數字替換成 'H',引數 1 表示只替換 1 個,不寫表示替換全部

#sub
ret = re.sub('\d', 'H', 'eva3egon4yuan4',1)
print(ret) #evaHegon4yuan4

 

subn
將數字替換成 'H',返回元組 ( 替換的結果,替換了多少次 )

#subn
ret = re.subn('\d', 'H', 'eva3egon4yuan4')
print(ret)

 

compile
一般用於一條正則規則要反反覆覆使用或一條規則特別長的時候使用

#compile
#將正則表示式編譯成為一個 正則表示式物件,規則要匹配的是3個數字
obj = re.compile('\d{3}')
ret = obj.search('abc123eeee') #正則表示式物件呼叫search,引數為待匹配的字串
print(ret.group())  #結果 : 123
ret = obj.search('abcashgjgsdghkash456eeee3wr2') #正則表示式物件呼叫search,引數為待匹配的字串
print(ret.group())  #結果 : 456

 

finditer
返回一個存放匹配結果的迭代器,當所找的東西很對時

#finditer
ret = re.finditer('\d', 'ds3sy4784a')   
print(ret)  # <callable_iterator object at 0x10195f940>
# print(next(ret).group())  #檢視第一個結果
# print(next(ret).group())  #檢視第二個結果
# print([i.group() for i in ret])  #檢視剩餘的左右結果
for i in ret:
    print(i.group()) # .group()可以取出所有值

 

分組優先的問題

 

findall 存在的問題
這是因為 findall 會優先把匹配結果組裡內容返回,如果想要匹配結果,取消許可權即可

#findall 取值的問題
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']

# 這裡使用 ? 來取消分組優先
ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['www.oldboy.com']

 

split的優先順序查詢

#split 應該注意的問題
ret=re.split("\d+","eva3egon4yuan")
print(ret) #結果 : ['eva', 'egon', 'yuan']

ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #結果 : ['eva', '3', 'egon', '4', 'yuan']

#在匹配部分加上()之後所切出的結果是不同的,
#沒有()的沒有保留所匹配的項,但是有()的卻能夠保留了匹配的項,
#這個在某些需要保留匹配部分的使用過程是非常重要的

 

flags 有很多可選值:

re.I(IGNORECASE)   忽略大小寫,括號內是完整的寫法
re.M(MULTILINE)      多行模式,改變^和$的行為
re.S(DOTALL)           點可以匹配任意字元,包括換行符
re.L(LOCALE)      做本地化識別的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境,不推薦使用
re.U(UNICODE)      使用 \w \W \s \S \d \D 使用取決於 unicode 定義的字元屬性。在 python3 中預設使用該 flag
re.X(VERBOSE)        冗長模式,該模式下 pattern 字串可以是多行的,忽略空白字元,並可以添加註釋