compile(), search() & findall()
#!python3
import re
regex = re.compile(r'\d{4}-?\d{6}') # r 表示使用 Raw string,即不 escape 反斜線
s = '手機號碼有兩種,第一種是 0912-345678,第二種是 0912345678。'
# search 只會找到第一個符合的
mo = regex.search(s)
if mo != None:
print(mo.group())
# 0912-345678
# findall 會找到全部符合的
mo = regex.findall(s)
for mo in mobile_regex.findall(s):
print(mo)
# 0912-345678
# 0912345678
Raw string 請參考 Java 腦袋學 Python 字串,如果不用 Raw string,那所有反斜線都要改用兩個反斜線,這樣變得很麻煩而且讓原本就難以閱讀的 RE 語法變得更加外星語。快速複習 RE
- \d 表示 0 到 9 的數字,也可以用 [0-9] 或者 (0|1|2|3|4|5|6|7|8|9) 表示
- \D 表示 0 到 9 以外的任何字元,包括空白,也可以用 [^0-9] 表示
- \w 表示字母、數字與底線,可以當作單字,也可以用 [a-zA-Z0-9_] 表示
- \W 表示 \w 以外的任何字元,包括空白,也可以用 [^a-zA-Z0-9_] 表示
- \s 表示空白、\t 與 \n,可以當作空白字元
- \S 表示 \s 以外的任何字元
- 自訂字元用中括號 [] 包起來,也可以使用 - 連字號指定字母與數字的範圍
- 在中括號裡可以直接使用特殊字元,不用 \ Escape
- 在中括號裡第一個字元使用 ^ 表示指定相反的字元集合
- ^ 開頭與 $ 結尾
- . 表示換行字元之外的任何字元,但對應的只有一個字元
- .* 表示換行字元以外的所有字元,且為貪婪模式
- .*? 表示換行字元以外的所有字元,但為非貪婪模式
- 非貪婪模式可以用在 {S,E}?、*? 與 +?
- 分組用 ( 與 )
- 或 |
- 出現零次或一次 ?
- 出現零次或 N 次 *
- 出現一次以上 +
- 出現指定次數 {N}、{S, E}、{S,}、{,E}
要找上述的特殊符號,就用 \ Escape。
指定字元
#!python3
import re
s = 'javascript java8 spring4 python3 css'
for mo in re.compile(r'\w+\d').findall(s):
print(mo)
# java8
# spring4
# python3
Group 分組
#!python3
import re
# 用括弧分組
regex = re.compile(r'(\d{2})-(\d{8})')
s = '先來找簡單的電話號碼 04-22334455'
# search 只會找到第一個符合的
mo = regex.search(s)
print(mo.group()) # 04-22334455 符合字串
print(mo.group(0)) # 04-22334455 符合字串
print(mo.group(1)) # 04 符合字串的第一個分組
print(mo.group(2)) # 22334455 符合字串的第二個分組
print(mo.groups()) # ('04', '22334455') tuple 組成的分組
area, number = mo.groups()
print('{}-{}'.format(area, number)) # 04-22334455
或 |
#!python3
import re
regex = re.compile(r'python|java')
s = 'java spring python hibernate'
for mo in regex.findall(s):
print(mo)
# java
# python
或也可以用 []。#!python3
import re
regex = re.compile(r'[Pp]ython')
s = 'Python PYthon python'
for mo in regex.findall(s):
print(mo)
# Python
# python
指定次數 ? * + { }
#!python3
import re
s = 'br bar baar baaar baaaar baaaaar'
# 零次或一次
for mo in re.compile(r'ba?r').findall(s):
print(mo)
# br
# bar
# 零次或 N 次
for mo in re.compile(r'ba*r').findall(s):
print(mo)
# br
# bar
# baar
# baaar
# baaaar
# baaaaar
# 一次以上
for mo in re.compile(r'ba+r').findall(s):
print(mo)
# bar
# baar
# baaar
# baaaar
# baaaaar
# 指定次數{N}
for mo in re.compile(r'ba{3}r').findall(s):
print(mo)
# baaar
# 指定次數 {S,E}
for mo in re.compile(r'ba{1,3}r').findall(s):
print(mo)
# bar
# baar
# baaar
# 指定次數 {S,}
for mo in re.compile(r'ba{3,}r').findall(s):
print(mo)
# baaar
# baaaar
# baaaaar
# 指定次數 {,E}
for mo in re.compile(r'ba{,3}r').findall(s):
print(mo)
# br
# bar
# baar
# baaar
Greedy 貪婪模式
Python 預設是貪婪模式,即在符合條件的情況下,會找出最長的字串,例如 x{3,5} 可以找到五個 x 的話,就不會在 3 個 x 就結束。可以在大括號後面加上 ?,改為非貪婪模式。
#!python3
import re
s = 'f fo foo fooo foooo fooooo'
for mo in re.compile(r'fo{1,3}').findall(s):
print(mo)
# fo
# foo
# fooo
# fooo
# fooo
# 非貪婪模式
for mo in re.compile(r'fo{1,3}?').findall(s):
print(mo)
# fo
# fo
# fo
# fo
# fo
findall() & Group 分組
findall() 會回傳所有符合的結果,但依據 RE 內容的不同而有不同的回傳物件。當內容沒有分組時,回傳的是 list of str,但是有分組時,回傳的是 list of tuple。
#!python3
import re
s = '04-22334455 0912-345678 04-23456789'
for mo in re.compile(r'\d{2}-\d{8}').findall(s):
print(mo)
# 04-22334455
# 04-23456789
s = '04-22334455 04-23456789'
for mo in re.compile(r'(\d{2})-(\d{8})').findall(s):
print(mo)
# ('04', '22334455')
# ('04', '23456789')
額外的參數
re.DOTALL 讓 . 包括換行字元。#!python3 import re s = 'Ba\na\nar' print(re.compile(r'B.*?r').search(s)) # None print(re.compile(r'B.*?r', re.DOTALL).search(s).group()) # Ba\na\narre.IGNORECASE 或 re.I 不區分大小寫。
#!python3
import re
s = 'java Java JAVA'
for mo in re.compile(r'java').findall(s):
print(mo)
# java
for mo in re.compile(r'java', re.IGNORECASE).findall(s):
print(mo)
# java
# Java
# JAVA
# re.I 也行
for mo in re.compile(r'java', re.I).findall(s):
print(mo)
# java
# Java
# JAVA
同時使用 re.DOTALL 與 re.IGNORECASE。#!python3 import re s = 'Ba\na\nar' print(re.compile(r'b.*?r', re.DOTALL | re.IGNORECASE).search(s).group()) # Ba\na\nar
取代符合字串
用 sub() 取代 search() 或 findall()。#!python3 import re s = 'Python python' print(re.compile(r'y').sub(r'*', s)) # P*thon p*thon用原字串取代,使用 \N 表示分組 N,注意取代字串也是使用 Raw string 唷。
#!python3 import re s = 'Python python' print(re.compile(r'(python)', re.I).sub(r'[\1]', s)) # [Python] [python]
複雜的分組
當分組裡有分組時,如何判斷分組順序?依照左括號出現的順序。#!python3 import re s = 'Python3 python2' print(re.compile(r'((python)(\d))', re.I).sub(r'\2[\3]', s)) # Python[3] python[2]\1 表示 Python3 或 python2,\2 表示 Python 或 python,而 \3 表示 3 或 2。
分行並註解的語法
可以透過 re.VERBOSE 參數來使用多行模式('''),並可加入註解。#!python3
import re
s = '1976-7-6 2017-1-7'
print(re.compile(r'''
((19|20)\d\d # 年
-
[0-1]?\d # 月
-
[0-3]?\d) # 日
''', re.VERBOSE).findall(s))
# [('1976-7-6', '19'), ('2017-1-7', '20')]
------
---
Very helpful post, this institute builds confidence through hands-on sessions.
回覆刪除best java institute in hyderabad