1. Python正則式的基本用法
1.1基本規則
1.2重複
1.2.1最小匹配與精確匹配
1.3前向界定與後向界定
1.4組的基本知識
2. re模組的基本函數
2.1使用compile加速
2.2 match和search
2.3 finditer
2.4 字串的修改與替換
3. 更深入的瞭解re的組與對象
3.1編譯後的Pattern對象
3.2 組與Match對象
3.2.1組的名字與序號
3.2.2 Match對象的方法
4. 更多的資料
初學Python,對Python的文文書處理能力有很深的印象,除了str對象內建的一些方法外,就是Regex這個強大的模組了。但是對 於初學者來說,要用好這個功能還是有點難度,我花了好長時間才摸出了點門道。由於我記性不好,很容易就忘事,所以還是寫下來比較好一些,同時也可以加深印 象,整理思路。
由於我是初學,所以肯定會有些錯誤,還望高手不吝賜教,指出我的錯誤。
1 Python正則式的基本用法
Python的Regex的模組是 ‘re’,它的基本文法規則就是指定一個字元序列,比如你要在一個字串s=’123abc456’ 中尋找字串 ’abc’,只要這樣寫:
>>> import re
>>> s='123abc456eabc789'
>>> re.findall(r’abc’,s)
結果就是:
['abc', 'abc']
這裡用到的函數 ”findall(rule , target [,flag] )” 是個比較直觀的函數,就是在目標字串中尋找符合規則的字串。第一個參數是規則,第二個參數是目標字串,後面還可以跟一個規則選項(選項功能將在 compile函數的說明中詳細說明)。返回結果結果是一個列表,中間存放的是符合規則的字串。如果沒有符合規則的字串被找到,就返回一個空列表。
為什麼要用r’ ..‘字串(raw字串)? 由於正則式的規則也是由一個字串定義的,而在正則式中大量使用逸出字元’\’,如果不用raw字串,則在需要寫一個’\’的地方,你必須得寫成’ \\’,那麼在要從目標字串中匹配一個’\’的時候,你就得寫上4個’\’成為’\\\\’!這當然很麻煩,也不直觀,所以一般都使用r’’來定義規則 字串。當然,某些情況下,可能不用raw字串比較好。
以上是個最簡單的例子。當然實際中這麼簡單的用法幾乎沒有意義。為了實現複雜的規則尋找,re規定了若干文法規則。它們分為這麼幾類:
功能字元 : ‘.’ ‘*’ ‘+’ ‘|’ ‘?’ ‘^’ ‘$’ ‘\’ 等,它們有特殊的功能含義。特別是’\’字元,它是轉義引導符號,跟在它後面的字元一般有特殊的含義。
規則分界符: ‘[‘ ‘]’ ‘(’ ‘)’ ‘{‘ ‘}’ 等,也就是幾種括弧了。
預定義逸出字元集: “\d” “\w” “\s” 等等,它們是以字元’\’開頭,後面接一個特定字元的形式,用來指示一個預定義好的含義。
其它特殊功能字元: ’#’ ‘!’ ‘:’ ‘-‘等,它們只在特定的情況下表示特殊的含義,比如(?# …)就表示一個注釋,裡面的內容會被忽略。
下面來一個一個的說明這些規則的含義,不過說明的順序並不是按照上面的順序來的,而是我認為由淺入深,由基本到複雜的順序來編排的。同時為了直觀,在說明的過程中盡量多舉些例子以方便理解。
1.1 基本規則
‘[‘ ‘]’ 字元集合設定符
首先說明一下字元集合設定的方法。由一對方括弧括起來的字元,表明一個字元集合,能夠匹配包含在其中的任意一個字元。比如 [abc123],表明字元’a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’都符合它的要求。可以被匹配。
在’[‘ ‘]’中還可以通過 ’-‘ 減號來指定一個字元集合的範圍,比如可以用[a-zA-Z]來指定所以英文字母的大小寫,因為英文字母是按照從小到大的順序來排的。你不可以把大小的順序顛倒了,比如寫成[z-a]就不對了。
如果在’[‘ ‘]’裡面的開頭寫一個 ‘^’ 號,則表示取非,即在括弧裡的字元都不匹配。如[^a-zA-Z]表明不匹配所有英文字母。但是如果 ‘^’不在開頭,則它就不再是表示取非,而表示其本身,如[a-z^A-Z]表明匹配所有的英文字母和字元’^’。
‘|’ 或規則
將兩個規則並列起來,以‘|’串連,表示只要滿足其中之一就可以匹配。比如
[a-zA-Z]|[0-9] 表示滿足數字或字母就可以匹配,這個規則等價於 [a-zA-Z0-9]
注意:關於’|’要注意兩點:
第一, 它在’[‘ ‘]’之中不再表示或,而表示他本身的字元。如果要在’[‘ ‘]’外面表示一個’|’字元,必須用反斜線引導,即 ’\|’ ;
第二, 它的有效範圍是它兩邊的整條規則,比如‘dog|cat’匹配的是‘dog’和’cat’,而不是’g’和’c’。如果想限定它的有效範圍,必需使用一個 無擷取的群組 ‘(?: )’包起來。比如要匹配 ‘I have a dog’或’I have a cat’,需要寫成r’I have a (?:dog|cat)’ ,而不能寫成 r’I have a dog|cat’
例
>>> s = ‘I have a dog , I have a cat’
>>> re.findall( r’I have a (?:dog|cat)’ , s )
['I have a dog', 'I have a cat'] #正如我們所要的
下面再看看不用無擷取的群組會是什麼後果:
>>> re.findall( r’I have a dog|cat’ , s )
['I have a dog', 'cat'] #它將’I have a dog’ 和’cat’當成兩個規則了
至於無擷取的群組的使用,後面將仔細說明。這裡先跳過。
‘.’ 匹配所有字元
匹配除分行符號’\n’外的所有字元。如果使用了’S’選項,匹配包括’\n’的所有字元。
例:
>>> s=’123 \n456 \n789’
>>> findall(r‘.+’,s)
['123', '456', '789']
>>> re.findall(r‘.+’ , s , re.S)
['123\n456\n789']
‘^’和’$’ 匹配字串開頭和結尾
注意’^’不能在‘[ ]’中,否則含意就發生變化,具體請看上面的’[‘ ‘]’說明。 在多行模式下,它們可以匹配每一行的行首和行尾。具體請看後面compile函數說明的’M’選項部分
‘\d’ 匹配數字
這是一個以’\’開頭的逸出字元,’\d’表示匹配一個數字,即等價於[0-9]
‘\D’ 匹配非數字
這個是上面的反集,即匹配一個非數位字元,等價於[^0-9]。注意它們的大小寫。下面我們還將看到Python的正則規則中很多逸出字元的大小寫形式,代表互補的關係。這樣很好記。
‘\w’ 匹配字母和數字
匹配所有的英文字母和數字,即等價於[a-zA-Z0-9]。
‘\W’ 匹配非英文字母和數字
即’\w’的補集,等價於[^a-zA-Z0-9]。
‘\s’ 匹配間隔符
即匹配空格符、定位字元、斷行符號符等表示分隔意義的字元,它等價於[ \t\r\n\f\v]。(注意最前面有個空格)
‘\S’ 匹配非間隔符
即間隔符的補集,等價於[^ \t\r\n\f\v]
‘\A’ 匹配字串開頭
匹配字串的開頭。它和’^’的區別是,’\A’只匹配整個字串的開頭,即使在’M’模式下,它也不會匹配其它行的很首。
‘\Z’ 匹配字串結尾
匹配字串的結尾。它和’$’的區別是,’\Z’只匹配整個字串的結尾,即使在’M’模式下,它也不會匹配其它各行的行尾。
例:
>>> s= '12 34\n56 78\n90'
>>> re.findall( r'^\d+' , s , re.M ) #匹配位於行首的數字
['12', '56', '90']
>>> re.findall( r’\A\d+’, s , re.M ) #匹配位於字串開頭的數字
['12']
>>> re.findall( r'\d+$' , s , re.M ) #匹配位於行尾的數字
['34', '78', '90']
>>> re.findall( r’\d+\Z’ , s , re.M ) #匹配位於字串尾的數字
['90']
‘\b’ 匹配單詞邊界
它匹配一個單詞的邊界,比如空格等,不過它是一個‘0’長度字元,它匹配完的字串不會包括那個分界的字元。而如果用’\s’來匹配的話,則匹配出的字串中會包含那個分界符。
例:
>>> s = 'abc abcde bc bcd'
>>> re.findall( r’\bbc\b’ , s ) #匹配一個單獨的單詞 ‘bc’ ,而當它是其它單詞的一部分的時候不匹配
['bc'] #只找到了那個單獨的’bc’
>>> re.findall( r’\sbc\s’ , s ) #匹配一個單獨的單詞 ‘bc’
[' bc '] #只找到那個單獨的’bc’,不過注意前後有兩個空格,可能有點看不清楚
‘\B’ 匹配非邊界
和’\b’相反,它只匹配非邊界的字元。它同樣是個0長度字元。
接上例:
>>> re.findall( r’\Bbc\w+’ , s ) #匹配包含’bc’但不以’bc’為開頭的單詞
['bcde'] #成功匹配了’abcde’中的’bcde’,而沒有匹配’bcd’
‘(?:)’ 無擷取的群組
當你要將一部分規則作為一個整體對它進行某些操作,比如指定其重複次數時,你需要將這部分規則用’(?:’ ‘)’把它包圍起來,而不能僅僅只用一對括弧,那樣將得到絕對出人意料的結果。
例:匹配字串中重複的’ab’
>>> s=’ababab abbabb aabaab’
>>> re.findall( r’\b(?:ab)+\b’ , s )
['ababab']
如果僅使用一對括弧,看看會是什麼結果:
>>> re.findall( r’\b(ab)+\b’ , s )
['ab']
這是因為如果只使用一對括弧,那麼這就成為了一個組(group)。組的使用比較複雜,將在後面詳細講解。
‘(?# )’ 注釋
Python允許你在Regex中寫入注釋,在’(?#’ ‘)’之間的內容將被忽略。
(?iLmsux) 編譯選項指定
Python的正則式可以指定一些選項,這個選項可以寫在findall或compile的參數中,也可以寫在正則式裡,成為正則式的一部分。這在某些情況下會便利一些。具體的選項含義請看後面的compile函數的說明。
此處編譯選項’i’ 等價於IGNORECASE ,L 等價於 LOCAL ,m 等價於 MULTILINE ,s 等價於 DOTALL ,u 等價於 UNICODE , x 等價於 VERBOSE 。
請注意它們的大小寫。在使用時可以只指定一部分,比如只指定忽略大小寫,可寫為 ‘(?i)’,要同時忽略大小寫並使用多行模式,可以寫為 ‘(?im)’。
另外要注意選項的有效範圍是整條規則,即寫在規則的任何地方,選項都會對全部整條正則式有效。
1.2 重複
正則式需要匹配不定長的字串,那就一定需要表示重複的指示符。Python的正則式表示重複的功能很豐富靈活。重複規則的一般的形式是在一條字元規則後面緊跟一個表示重複次數的規則,已表明需要重複前面的規則一定的次數。重複規則有:
‘*’ 0或多次匹配
表示匹配前面的規則0次或多次。
‘+’ 1次或多次匹配
表示匹配前面的規則至少1次,可以多次匹配
例:匹配以下字串中的前一部分是字母,後一部分是數字或沒有的變數名字
>>> s = ‘ aaa bbb111 cc22cc 33dd ‘
>>> re.findall( r’\b[a-z]+\d*\b’ , s ) #必須至少1個字母開頭,以連續數字結尾或沒有數字
['aaa', 'bbb111']
注意上例中規則前後加了表示單詞邊界的’\b’指示符,如果不加的話結果就會變成:
>>> re.findall( r’[a-z]+\d*’ , s )
['aaa', 'bbb111', 'cc22', 'cc', 'dd'] #把單詞給拆開了
大多數情況下這不是我們期望的結果。
‘?’ 0或1次匹配
只匹配前面的規則0次或1次。
例,匹配一個數字,這個數字可以是一個整數,也可以是一個科學計數法記錄的數字,比如123和10e3都是正確的數字。
>>> s = ‘ 123 10e3 20e4e4 30ee5 ‘
>>> re.findall( r’ \b\d+[eE]?\d*\b’ , s )
['123', '10e3']
它正確匹配了123和10e3,正是我們期望的。注意前後的’\b’的使用,否則將得到不期望的結果。
註:此內容是從互連網上搜取轉載的!