python的正則表達式

re模塊

re模塊是python中處理正則表達式的一個模塊,通過re模塊的方法,把正則表達式pattern編譯成正則對象,以便使用正則對象的方法。

正則語法

首先推薦一個在線的正則表達式驗證調試網站regular expressions 101。支持pythonjavascriptpythongolang4種語言的正則語法。使用時注意勾選正確的語言。
正則表達式中的字符分爲普通字符元字符,通過普通字符和元字符組合成一個特定匹配規則的表達式。除元字符之外的都是普通字符。下面介紹部分元字符。

  • 單個字符匹配
    . 匹配換行符\n之外的任意一個字符。
    [...] 表示一個字符集集合。被匹配的文本對應位置可以是這個字符集合中指定的任意字符。
    [^...] 表示匹配除該字符集合指定的字符外的其它所有字符中的任意一個。
    \ 轉義字符,可以用來改變特殊字符的原有含義。
  • 預定義字符集
    \d 數字 [0-9]
    \D 非數字 [^\d]
    \s 空白字符 [<空格>\t\r\n\f\v]
    \S 非空白字母 [^\s]
    \w 單詞字符 [A-Za-z0-9]
    \W 非單詞字符 [^\w]
  • 字符次數匹配
    * 匹配前一個字符0或無限次
    + 匹配前一個字符1或無限次
    ? 匹配前一個字符0或1次
    {m} 匹配前一個字符m次
    {m, n} 匹配前一個字符m至n次。
    *? + ???(m,n)? 使變成非貪婪模式
  • 邊界匹配
    ^ 匹配字符串開頭。多行模式下匹配每一行的開頭。
    $ 匹配字符串末尾。多行模式下匹配每一行的末尾。
    \A 僅匹配字符串開頭。
    \Z 僅匹配字符串末尾。
    \b 匹配\w和\W之間。
    \B [^\b]
  • 邏輯與分組
    | 表示邏輯或,代表它左右兩邊的表達式會任意匹配一個。總是優先匹配左邊的表達式,若匹配成功則跳過右邊的表達式匹配。若|沒有出現在()中,則它的有效範圍是整個正則表達式。
    (...) 被括起來的表達式表示一個分組,且每一個分組都有一個正整數編號,從表達式開始每遇到一個分組的左括號,分組編號就+1,。另外,分組表達式作爲一個整體,後面可接表示詞次數的字符。分組表達式中的|僅在該分組中有效。
    (?P<NAME...>) 表示一個分組,除了原有的分組編號外,又指定了一個分組名稱。
    \<number> 引用編號爲<number>的分組所匹配到的字符串。
    (?P=name) 引用名稱爲name的分組所匹配到的字符串。
  • 特殊構造
    (?:...) (…)的不分組版本,用於使用|或後接數量詞。
    (?#...) #後的內容將作爲註釋被忽略。
    (?=...) 後面的字符串內容需要匹配表達式才能成功匹配。不消耗字符串的內容。
    (?<=...) 前面的字符串內容需要匹配表達式才能成功匹配。不消耗字符串的內容。
    (?!...) 後面的字符串內容需要不匹配表達式才能成功匹配。不消耗字符串內容。
    (?<!...) 前面的字符串內容需要不匹配表達式才能成功匹配。不消耗字符串內容。
    (?iLmsux)
    (?(id/name)yes-pattern|no-pattern) 編號爲id或別名爲name的分組匹配到字符,則需要匹配yes-pattern表達式,否則需要匹配no-pattern表達式。|no-pattern可以省略。

關於更多的邏輯分組、特殊構造可以查看下錶。

re使用方法

compile(pattern, flags=0)

    使用compile()函數編譯正則表達式,返回正則表達式對象。

import re

p = re.compile(r'[a-z]+')
print(type(p))
輸出結果:  <class '_sre.SRE_Pattern'>

表達式對象的方法和屬性
通過compile()函數返回的就是表達式對象

match(self, string, pos=0, endpos=-1)
    在string字符串開始位置匹配正則表達式,如果0個或者多個字符被匹配則返回相應的匹配對象,如果不匹配則返回None。

import re
p = re.compile(r'[a-z]+')
print(re.match(p, 'hello'))
#輸出結果:<_sre.SRE_Match object; span=(0, 5), match='hello'>
print(re.match(p, '123123'))
#輸出結果: None
fullmatch(self, string, pos=0, endpos=-1)
    整個string字符串與該正則表達式對象匹配則返回相應的匹配對象,否則返回None。相當於給正則表達式加上了邊界字元字符^$

import re
p = re.compile(r'[a-z]+')
print(re.match(p, 'hello'))
#輸出結果: <_sre.SRE_Match object; span=(0, 5), match='hello'>
print(re.match(p, '123123'))
#輸出結果: None
search(self, string, pos=0, endpos=-1)
    掃描整個string字符串,查找正則表達式對象可以匹配的子串第一次出現的位置,並返回相應的匹配對象,如果沒有匹配的內容則返回None。
search()在字符串的任意位置進行匹配檢測;match僅在字符串開始位置進行匹配檢測。

import re
f = 'abcdefg' print(re.search(r'^c', f))
#輸出結果: None print(re.search(r'^a', f))
#輸出結果:<_sre.SRE_Match object; span=(0, 1), match='a'>
findall(self, string, pos=0, endpos=-1)
    搜索string字符串中與正則表達式匹配的所有子串,以列表形式返回。

import re
test = "He was carefully disguised but captured quickly by police." ##查找以ly結尾的單詞 print(re.findall(r'\w+ly', test))   
#輸出結果:  ['carefully', 'quickly']
finditer(self, string, pos=0, endpos=-1)

    搜索string字符串中與正則表達式匹配的所有子串,以迭代器形式返回。

import re
test = "He was carefully disguised but captured quickly by police."  for i in re.finditer(r'\w+ly', test):
    print("{0}-{1}:{2}".format(i.start(), i.end(), i.group()))
#輸出結果: 7-16:carefully
40-47:quickly
sub(self, repl, string, count=0)
替換string字符串中與正則表達式匹配的count個子串,返回替換修改後的字符串。

import re

test = "pro--gr-am" print(re.sub(r'-+', '', test))
#輸出結果: program
split(self, string, maxsplit=0)
以正則表達式匹配的字符串爲分隔符,對一個字符串進行分割,以列表形式返回分隔後的各個字符串。

import re

test = "Words, words, words." print(re.split(r'\W+', test))  #非字母和數字 作爲 分隔符 #輸出結果: ['Words', 'words', 'words', '']
上述方法中部分參數說明
string  要匹配或處理的字符串
pos  表示從string字符串的哪個位置開始
endpos  表示到string字符串的哪個位置結束
maxsplit  表示最大切割次數,默認值0,表示能切割多少次就儘可能多的切割多少次


匹配對象的方法
用正則表達式對象的regex.match()、regex.fullmatch()和regex.search()得到的結果就是一個匹配對象

  • group(self, *args)
    返回一個或多個指定捕獲組匹配到的內容。若只有一個參數則返回值是一個單獨的字符串;若有多個參數則返回值是包含每一個指定分組所對應的匹配字符串的元組;若不指定參數,則group1默認爲0,將返回整個正則表達式所匹配的內容。
  • groups(self, default=None)
    返回一個包含所有分組所匹配內容的元組,如果某個分組沒有匹配的內容,則取default所指定的值。
  • groupdict(self, default=None)
    返回一個包含所有命名分組名稱及其所匹配內容的字典對象,如果某個分組沒有匹配的內容,則取default所指定的值。
  • start()
    返回匹配到內容的開始位置。
  • end()
    返回匹配到內容的結束位置。
  • span()
    返回包含匹配到內容開始和結束位置的元組(start, end)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    >>> import re
    >>> p = re.compile(r'.*name\s+is\s+(\w+).*am\s+(?P<age>\d{1,3})\s+years.*tel\s+is\s+(?P<tel>\d{11}).*', re.DOTALL)
    >>> string = '''
    ... My name is Tom,
    ... I am 16 years old,
    ... My tel is 13972773480.
    ... '''
    >>> m = p.match(string)
    >>> print(m.group())
    
    My name is Tom,
    I am 16 years old,
    My tel is 13972773480.
    
    >>> print(m.group(0))
    
    My name is Tom,
    I am 16 years old,
    My tel is 13972773480.
    
    >>> print(m.group(1))
    Tom
    >>> print(m.group(2))
    16
    >>> print(m.group(3))
    13972773480
    >>> print(m.group('tel'))
    13972773480
    >>> print(m.groups())
    ('Tom', '16', '13972773480')
    >>> print(m.groupdict())
    {'age': '16', 'tel': '13972773480'}
    

re在模塊級別提供的函數如下

1
2
3
4
5
6
match(pattern, string, flags=0)
fullmatch(pattern, string, flags=0)
search(pattern, string, flags=0)
findall(pattern, string, flags=0)
sub(pattern, repl, string, count=0, flags=0)
split(pattern, string, maxsplit=0, flags=0)

函數名稱和re對象所提供的函數名稱同名,其實就是正則表達式對象方法的封裝,功能相同。
通過complie()聲明正則對象,然後調用正則對象方法效率比直接使用模塊級別函數高。

  • 正則表達式的r前綴
    對於一些特殊的字符需要通過/(反斜線)進行轉義處理才能被正確的識別。加上r(raw,原始的意思)表示字符串的字面值就是其真實值,不需要進行轉義等操作。

關於python正則語法,可以點擊Regular Expression HOWTO查看更多內容。

關於python正則模塊使用,可以點擊 Regular expression operations查看更多內容。


 數量詞的貪婪模式與非貪婪模式

    正則表達式通常用於在文本中查找匹配的字符串。

    Python裏數量詞默認是貪婪的(在少數語言裏也可能是默認非貪婪),總是嘗試匹配儘可能多的字符;非貪婪的則相反,總是嘗試匹配儘可能少的字符。例如:正則表達式"ab*"如果用於查找"abbbc",將找到"abbb"。而如果使用非貪婪的數量詞"ab*?",將找到"a"。