1. 程式人生 > >正則表示式 Regular Expression

正則表示式 Regular Expression

背景定義

    每次臨時用正則表示式,理解和學習的一知半解。乾脆慢慢總結一下,以後更新。其中看到的很多相關教程都標識在reference中,文中部分內容直接來自參考教程,沒有一一標註。非常感謝他們的總結。     自己對正則表示式的理解就是定義一個字串的結構模式,在文字中去匹配符合該模式的字串。使用match()、search()、findall()等常用方法去匹配,split()和sub()函式則匹配後做分割和替換,功能合二為一。然後可以通過match object函式得到匹配後的結果。

模式語言

    如何去構造模式?用什麼樣的符號,以什麼樣的方式去構造模式?     例如,\d可以匹配一個數字;\w可以匹配一個字母或數字;.可以匹配任意字元;用*表示任意個字元(包括0個),用+表示至少一個字元,用?表示0個或1個字元,用{n}表示n個字元,用{n,m}表示n-m個字元。

  • ‘00\d’可以匹配’007’,但無法匹配’00A’;
  • ‘\d\d\d’可以匹配’010’;
  • ‘\w\w\d’可以匹配’py3’;
  • 'py.‘可以匹配’pyc’、‘pyo’、'py!'等等;
  • \d{3}表示匹配3個數字,例如’010’;
  • \d{3,8}表示3-8個數字,例如’1234567’。

匹配字元的操作符

操作符 含義
. 表示任何單個字元,除了換行符 當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字元。
\w 匹配字母數字及下劃線
\W 匹配非字母數字及下劃線
\s 匹配任意空白字元,等價於 [\t\n\r\f].
\S 匹配任意非空字元
\d 匹配任意數字,等價於 [0-9].
\D 匹配任意非數字
\n 匹配一個換行符
\t 匹配一個製表符

匹配數量的操作符

操作符 含義
* 前一個字元0次或無限次擴充套件 abc*表示ab、abc、abcc、abccc等
+ 前一個字元1次或無限次擴充套件 abc+表示abc、abcc、abccc等
? 前一個字元0次或1次擴充套件 abc?表示ab、abc
| 左右表示式任意一個 abc|def表示abc或def
{m} 擴充套件前一個字元m次 ab{2}c表示abbc
{m,n} 擴充套件前一個字元m至n次(含n) ab{1,2}c表示abc、abbc

匹配集合的操作符

操作符 含義
[] 字符集,對單個字元給出取值範圍 [abc]表示a、b、c,[a-z]表示a到z單個字元 [0-9] 等價於\d [A-Za-z0-9_]等價於\w
[^] 非字符集,對單個字元給出排除範圍 [^abc]表示非a或b或c的單個字元
() 分組標記,內部只能使用|操作符 (abc)表示abc,(abc|def)表示abc、def

匹配位置的操作符

操作符 含義
^ 匹配字串開頭 ^abc表示abc且在一個字串的開頭
$ 匹配字串結尾 abc$表示abc且在一個字串的結尾
\A 匹配字串開始
\Z 匹配字串結束,如果是存在換行,只匹配到換行前的結束字串。
\z 匹配字串結束
\G 匹配最後匹配完成的位置。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。 ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非單詞邊界。 ‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。

常用例項

Pattern 含義
[0-9] 匹配任何數字。類似於 [0123456789]
[a-z] 匹配任何小寫字母
[A-Z] 匹配任何大寫字母
[a-zA-Z0-9] 匹配任何字母及數字
[^aeiou] 除了aeiou字母以外的所有字元
[^0-9] 匹配除了數字外的字元
^[A-Za-z]+$ 由26個字母組成的字串
^[A-Za-z0-9]+$ 由26個字母和數字組成的字串
^-?\d+$ 整數形式的字串
^[0-9]*[1-9][0-9]*$ 正整數形式的字串
[1-9]\d{5} 中國境內郵政編碼,6位
[\u4e00-\u9fa5] 匹配中文字元
\d{3}-\d{8}|\d{4}-\d{7} 國內電話號碼,010-68913536或0558-1234567

常用函式

re 模組使 Python 語言擁有全部的正則表示式功能。

函式 — Functions 功能
re.search() 在一個字串中搜索匹配正則表示式的第一個位置,返回match物件(match object)
re.match() 從一個字串的開始位置起匹配正則表示式,返回match物件
re.findall() 搜尋字串,以列表型別返回全部能匹配的子串
re.split() 將一個字串按照正則表示式匹配結果進行分割,返回列表
re.finditer() 搜尋字串,返回一個匹配結果的迭代型別,每一個迭代型別是match物件
re.sub() 在一個字串中替換所有匹配正則表示式的子串,返回替換後的字串

re.compile(pattern[, flags])

compile 函式用於編譯正則表示式,生成一個正則表示式( Pattern )物件,供 match() 和 search() 這兩個函式使用。

re.search(pattern,string,flags=0)

在一個字串中搜索匹配正則表示式的第一個位置,返回match物件。

  • pattern:正則表示式的字串或原生字串表示
  • string:待匹配字串
  • flags:正則表示式使用時的控制標記
修飾符 描述
re.I 使匹配對大小寫不敏感 同re.IGNORECASE
re.L 做本地化識別(locale-aware)匹配
re.M 多行匹配,影響 ^ 和 $ 同re.MULTILINE
re.S 使 . 匹配包括換行在內的所有字元
re.U 根據Unicode字符集解析字元。這個標誌影響 \w, \W, \b, \B.
re.X 該標誌通過給予你更靈活的格式以便你將正則表示式寫得更易於理解。
m = re.search('foo', 'seafood')
if m is not None:
    print(m.group())
else:
    print("no match")

output: foo

re.match(pattern, string, flags=0)

匹配成功re.match方法返回一個匹配的物件,否則返回None。

m = re.match('foo', 'seafood')
if m is not None:
    print(m.groups())
else:
    print("no match")

output: no match

使用group(num) 或 groups() 匹配物件函式來獲取匹配表示式。

方法 描述
group(num=0) 匹配的整個表示式的字串,group() 可以一次輸入多個組號,在這種情況下它將返回一個包含那些組所對應值的元組。
groups() 返回一個包含所有小組字串的元組,從 1 到 所含的小組號。
m=re.match(r'(\d{3})\-(\d{3,8})$', '010-12345')
m.group() #output: '010-12345'
m.group(0) #output: '010-12345'
m.group(1) #output: '010'
m.group(2) #output: '12345'
m.groups() #output: ('010', '12345')

re.match只匹配字串的開始,如果字串開始不符合正則表示式,則匹配失敗,函式返回None;而re.search匹配整個字串,直到找到一個匹配。

match(str, pos, endpos)

從pos位置開始匹配,結束位置為endpos。位置資訊預設為0和len(str)。

pattern = re.compile(r'dsa')
pattern.match('dsafww') #output: <_sre.SRE_Match object; span=(0, 3), match='dsa'>
pattern.match('dsdfdsafww',4) #output: <_sre.SRE_Match object; span=(4, 7), match='dsa'>
pattern.search('sadfadsaff') #output: <_sre.SRE_Match object; span=(5, 8), match='dsa'>

findall(str, pos, endpos)

返回所有匹配字串組成的list。

pattern = re.compile(r'\d+')
pattern.findall('abc2dfa3dsfasd5dfad') #output:['2', '3', '5']

finditer(str,pos,endpos)

找到所有匹配子串,返回由匹配結果(match object)組成的迭代器。

pattern = re.compile(r'\d+')
p = pattern.finditer('abc2fdas3klk9fds0dfdf')
print(p) #output:<callable_iterator object at 0x000002533754AE80>
for i in p:
    print(i) 
#output:<_sre.SRE_Match object; span=(3, 4), match='2'>
#output:<_sre.SRE_Match object; span=(8, 9), match='3'>
#output:<_sre.SRE_Match object; span=(12, 13), match='9'>
#output:<_sre.SRE_Match object; span=(16, 17), match='0'>
p = pattern.finditer('abc2fdas3klk9fds0dfdf')
for i in p:
    print(i.group())
#output:2
#output:3
#output:9
#output:0

re.split(pattern,string,maxsplit=0,flags=0)

將一個字串按照正則表示式匹配結果進行分割,返回列表型別。maxsplit:最大分隔數,剩餘部分作為最後一個元素輸出。

pattern = re.compile(r'[A-Z]+')
pattern.split("abcDefgHijkLmn") #output:['abc', 'efg', 'ijk', 'mn']
#Compare
'a b   c'.split(' ') #output:['a', 'b', '', '', 'c']
re.split(r'[\s\,\;]+','a,;b,  c') #output:['a', 'b', 'c']

sub(repl, string, count=0)

re.sub(pattern, repl, string, count=0, flags=0) 用repl替換string中每一個匹配的字串,返回替換後的字串,若找不到匹配,則返回源字串。 subn(),返回一個二元tuple(返回值,替換次數)。

pattern = re.compile(r'liKE', re.I)
pattern.sub(r'love', 'I like you, do u like me?') #output:'I love you, do u love me?'
pattern.subn(r'love', 'I like you, do u like me?') #output:('I love you, do u love me?', 2)

函式說明

match(), search(), findall(), finditer()這些既可以是pattern物件的函式,也可以模組直接呼叫,第一個引數為pattern。

match object函式

match.group()

返回match object中的字串。

pattern = re.compile(r'(\w+) (\w+)')
m = pattern.match('kobe bryant, lakers')
print(m) #output:<_sre.SRE_Match object; span=(0, 11), match='kobe bryant'>
print(m.group()) #output:kobe bryant
print(m.group(1)) #output:kobe
print(m.group(2)) #output:bryant
print(m.group(1,2)) #output:('kobe', 'bryant')
print(m.groups())  #output:('kobe', 'bryant')

match.goups()

返回由所有分組匹配到的字串組成的tuple。

match.start()

預設返回匹配字串的起始位置,指定引數時,返回該分組匹配到的字串的起始位置。

match.end()

返回結束位置。

match.span()

返回一個二元tuple表示匹配範圍。

m = re.match(r'(\d+)\.(\d+)', '24.12321')
print(m.groups()) #output:('24', '12321')
print(m.start()) #output:0
print(m.start(1)) #output:0
print(m.start(2)) #output:3
print(m.end()) #output:8
print(m.end(1)) #output:2
print(m.span()) #output:(0, 8)
print(m.span(1)) #output:(0, 2)
print(m.span(2)) #output:(3, 8)

Reference: