1. 程式人生 > >python標準庫:re

python標準庫:re

影響 obj 換行符 ctr 16px 結束 部分 tro local

1,匹配符號

  • * : 匹配前一個字符0次,1次,多次
  • + : 匹配前一個字符1次,多次
  • ? : 匹配前一個字符0次,1次
  • {n} : 匹配前一個字符n次
  • {n,} : 匹配前一個字符至少n次
  • {n,m} : 匹配前一個字符n到m次

  • . : 匹配任意一個字符(除了換行符/n),若指定flag
  • ^ : 匹配字符串開頭(無法匹配換行符後的位置)
  • $ : 匹配字符串結尾(無法匹配換行符前的位置)
  • | : 或
  • [] : 或
  • () : 捕獲分組,可以設置?:不捕獲分組

  • \A : 匹配字符串開始,與^的區別是\A不受MULTILINE影響?
  • \Z : 匹配字符結尾,與$的區別是\Z不受MULTILINE影響?
  • \d : 匹配數字
  • \D : 匹配非數字
  • \w : 匹配[a-zA-Z0-9]
  • \W : 匹配非[a-zA-Z0-9]
  • \s : 匹配空白字符, 即[\f\n\r\t\v]
  • \S : 匹配任何非空白字符,即[^ \f\n\r\t\v]
  • \b : 單詞邊界
  • \B : 非單詞邊界
  • [a-z] : 匹配任意小寫字母
  • [A-Z] : 匹配任意大寫字母
  • [a-zA-Z] : 匹配任意字母

2,匹配flags

  • MULTILINE(M):改變“^”和“$”,讓“^”能夠匹配到換行符後的位置,讓“$”能夠匹配到換行符前的位置
  • DOTALL(S):改變“.”,讓“.”能夠匹配換行符
  • IGNORECASE(I):忽略大小寫
  • LOCALE(L)
  • UNICODE(U)
  • VERBOSE(X)
  • ASCII(A)


3,匹配模式

  • 整體匹配(只匹配第一次):re.search / re.match
  • 全局匹配(匹配所有):re.findall
  • 分組捕獲:(),整體匹配和全局匹配都可以進行分組捕獲,捕獲匹配結果中的部分內容,分組捕獲可以嵌套,詳見匹配舉例


4,匹配寫法

方法一,需要重復執行匹配的,先編譯再匹配

regex = re.compile(p)

regex.search(s)

re.search(regex, s)

方法二,簡單的可以直接匹配

re.search(p, s)

5,匹配方法

1)re.search(p, s)

從s中提取完全符合p的內容,只提取第一次命中的,返回re.match對象

提取整體匹配結果:searchObj.group(), searchObj.group(0)

提取所有分組捕獲結果:searchObj.groups()

提取單個分組捕獲結果:searchObj.group(n), 即groups()[i] = group(i+1)

2)re.findall(p, s)

提取所有符合p的內容,返回字符串組成的列表

使用分組捕獲時,返回分組捕獲結果(元組)組成的列表

re.search使用分組捕獲時既可以捕獲整體匹配,也可以捕獲分組內容

re.findall使用分組捕獲時只能捕獲分組內容

3)re.match(p, s)

可以用re.search(^)替代

MULTILINE模式下,match也只匹配s,但re.search可以匹配換行後的開始

4)re.finditer(p, s)

re.findall的惰性版,返回iterator

5)re.split(p, s)

根據p分割字符串s

6)re.sub(p, repl, s, count=n)

p是匹配到的值,repl是替換後值,s是m目標字符串,count是替換多少次

6,分組捕獲時添加標簽

>>>ID = "310115199012128765"
>>>p = "(?P<dictrict>[0-9]{6})(?P<birthday>[0-9]{8})"
>>>re.search(p, ID).groupdict()
{‘dictrict‘: ‘310115‘, ‘birthday‘: ‘19901212‘}

7,懶惰匹配和貪婪匹配

.*是貪婪比配,盡可能多

.*?是懶惰匹配,滿足條件時,盡可能少

>>>re.search(‘a.*?b‘, ‘abab‘).group()
ab
>>>re.search(‘a.*?b‘, ‘abab‘).group()
abab
>>>re.search(‘192\.168\.1\..*$‘, ‘192.168.1.12‘).group() 
192.168.1.12
>>>re.search(‘192\.168\.1\..*?‘, ‘192.168.1.12‘).group() # 沒有結束符,懶惰不匹配
192.168.1.
>>>re.search(‘192\.168\.1\..*‘, ‘192.168.1.12‘).group() # 沒有結束符,貪婪匹配至最後
192.168.1.12

8,前向界定和後向界定

(?<=s):前向界定,s後面的位置

(?=s):後向界定,s前面的位置

>>>s = ‘ab1c ab2c\nab3c‘
>>>re.findall(‘(a.*?)(?:\s|$)‘, s) # 貌似$不能用[]或
[‘ab1c‘, ‘ab2c‘, ‘ab3c‘]
>>>re.findall(‘((?<=b).*?)(?:\s|$)‘, s) # b後面的位置開始
[‘1c‘, ‘2c‘, ‘3c‘]
>>>re.findall(‘((?=b).*?)(?:\s|$)‘, s) # b前面的位置開始
[‘b1c‘, ‘b2c‘, ‘b3c‘]

9,轉義

編程語言的轉義:

>>>s = ‘c:\name.txt‘
>>>print(‘c:\name.txt‘)
c:
ame.txt

不轉義就會被換行處理,解決方法是print(‘c:\\name.txt‘)或者print(r‘c:\name.txt‘)

正則表達式的轉義:

>>>s = ‘c:\\name.txt‘
>>>re.search(‘c:\\\\.*?\.‘, s).group()
‘c:\\name.‘
>>>re.search(r‘c:\\.*?\.‘, s).group()
‘c:\\name.‘

自動轉義:

有些編程語言沒有特殊意義的字符,可能無需轉義

例如print(‘\n)和print(‘\\n‘)不一樣

但是print(‘\d)和print(‘\\d‘)是一樣的


10,匹配舉例

‘ab1c ab2c\nab3c‘匹配例子:

>>>s = ‘ab1c ab2c\nab3c‘

>>>re.search(‘a.*?c a.*?c‘, s).group() # 整體匹配
ab1c ab2c
>>>re.search(‘a(.*?)c a(.*?)c‘, s).groups() # 整體匹配 + 捕獲分組
‘b1 b2‘
>>>re.search(‘a(\w(\w))c a(\w(\w))c‘, s).groups() # 整體匹配 + 捕獲分組
(‘b1‘, ‘1‘, ‘b2‘, ‘2‘)

>>>re.findall(‘a.*?c‘, s) # 全局匹配
[‘ab1c‘, ‘ab2c‘, ‘ab3c‘]
>>>re.findall(‘a(.*?)c‘, s) # 全局匹配 + 捕獲分組:只能捕獲分組內容
[‘b1‘, ‘b2‘, ‘b3‘]
>>>re.findall(‘a(\w(\w))c‘, s) # 全局匹配 + 捕獲分組嵌套
[(‘b1‘, ‘1‘), (‘b2‘, ‘2‘), (‘b3‘, ‘3‘)]

>>>re.findall(‘a.*?c$‘, s)
[‘ab3c‘]
>>>re.findall(‘a.*?c$‘, s, flags=re.M) # re.M影響$
[‘ab1c ab2c‘, ‘ab3c‘]
>>>re.findall(‘^a.*?c‘, s)
[‘ab1c‘]
>>>re.findall(‘^a.*?c‘, s, flags=re.M) # re.M影響^
[‘ab1c‘, ‘ab3c‘]
>>>re.search(‘a.*c‘, s).group()
‘ab1c ab2c‘
>>>re.search(‘a.*c‘, s, flags=re.DOTALL).group() # re.DOTALL影響.
‘ab1c ab2c\nab3c‘

>>>re.split(‘\s‘, s)
[‘ab1c‘, ‘ab2c‘, ‘ab3c‘]
>>>re.split(‘(\s)‘, s) # re.split + 分組可以看到分隔符
[‘ab1c‘, ‘ ‘, ‘ab2c‘, ‘\n‘, ‘ab3c‘]

‘a b, c ; d\ e‘匹配例子:

>>>s = ‘a b, c ; d\ e‘
>>>s
‘a b, c ; d\\ e‘  # \被自動轉成\>>>re.split(r‘\s*[\s,;\\]\s*‘, s)
[‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
>>>re.split(r‘\s*(?:\s|,|;|\\)\s*‘, s) # []的等效寫法
[‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
>>>re.split(r‘\s*(\s|,|;|\\)\s*‘, s) # 不用?:只抓到了單個分隔符,用它去對s分割會包含單個分隔符
[‘a‘, ‘ ‘, ‘b‘, ‘,‘, ‘c‘, ‘;‘, ‘d‘, ‘\\‘, ‘e‘]
>>> re.split(r‘(\s*(?:\s|,|;|\\)\s*)‘, s) # 包含完整的分隔符
[‘a‘, ‘ ‘, ‘b‘, ‘, ‘, ‘c‘, ‘ ; ‘, ‘d‘, ‘\\ ‘, ‘e‘]


  


  

python標準庫:re