Python 學習筆記 - 正則表達式模塊

在Python裏面,處理字符串除了基本的split,格式化操做等等,還可使用正則表達式。使用正則表達式,須要導入模塊re。正則自己也是一門語言,像下圍棋同樣,入門很容易,不過要玩的很溜就得花時間了。html


老實說,老男孩13期的正則表達式的視頻真的很爛,那個講課的估計是個新人,說話顛三倒四,邏輯混亂,豆子聽完仍是稀裏糊塗。python


課後在網上找到一篇強文正則表達式

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.htmlapp


拜讀以後,受益不淺。ide


基本規則以下所示:函數

wKioL1fWmZDyqQSPAAJ4eW9k7oo739.png


re模塊有下面幾個經常使用的函數spa


1. findall(pattern, string, flags=0),這個函數會返回一個列表,列表的元素是匹配到的字符串orm


例1,下面會匹配出以a開頭的全部單詞,\w+表示一個或者多個字母數字或者下劃線,由於不包括空格,因此至關於單個的單詞了視頻

>>> import re
ret=re.findall('a\w+','abc aaa bbh kjk hkk add')
print(ret)
['abc', 'aaa', 'add']


例2,在字符集裏面的元素能夠表示或的意義。字符集裏面特殊的字符會失去意義;可是他自己有2個特殊的字符,-表示範圍,^表示取反,好比說我須要查找加減乘除的符號,那麼-由於有特殊含義,所以須要用轉移符\轉義htm

>>> import re
a=re.findall('[+\-*/]\d','3+3-2*4/2')
print(a)
['+3', '-2', '*4', '/2']



2. search(pattern,string,flags)會經過pattern去匹配,若是匹配成功,會返回一個match對象,不然返回None。而後能夠經過group()函數獲取對象裏面的字符串


例3

>>> import re
obj = re.search('\d+', '123uuasf')
if obj:
    print(obj.group())
-------------
123


3. match(pattern,string,flags)會經過pattern去匹配,若是匹配成功,會返回一個match對象,不然返回None。而後能夠經過group()函數獲取對象裏面的字符串。他和search的區別在於match只能匹配字符串開頭的字符,後面的沒法匹配;而search能夠匹配到任意位置的字符串。


例4

import re
obj = re.match('\d+', 'u123uu888asf')
if obj:
    print(obj.group())
-------------
123


4.finditer(pattern,string,flags) 搜索string,返回一個順序訪問每個匹配結果(Match對象)的迭代器。 


例5,我但願匹配一個括號內的四則運算


注意他們的區別,search和match都返回了match對象,而後能夠經過group獲取字符串;而findall返回的是列表,由於我使用了圓括號分組,所以他會返回圓括號裏面的內容;如何獲取全部的內容呢,能夠經過 finditer,他至關於一個增強版的search,會找到全部match對象放入一個列表,咱們能夠循環這個列表而後獲取每一個元素的group內容。

>>> a=re.match('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))')
print(a.group())
print('search'.center(40,'-'))
a=re.search('\(([+\-*/]?\d+\.?\d*){1,}\)','2-(3*(2.2-3*3))')
print(a.group())
print('findall'.center(40,'-'))
a=re.findall('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))')
for item in a:
    print(item)
print('finditer'.center(40,'-'))
a=re.finditer('\(([+\-*/]?\d+\.?\d*){1,}\)','(-3.2)-2*2+(2-3*(22-3*3))')
for item in a:
    print(item.group())
-------------------------------------------
(-3.2)
-----------------search-----------------
(2.2-3*3)
----------------findall-----------------
-3.2
*3
----------------finditer----------------
(-3.2)
(22-3*3)


5.sub(pattern, repl, string, count=0, flags=0)

用於替換匹配的字符串


例6 替換2次

>>> ss='one,two,three'
print(re.sub('\w+','AAA',ss,2))
AAA,AAA,three


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


>>> a='i am ha happy man'
print(re.split('am',a))
-----------------
['i ', ' ha happy man']


除了上面的基本使用以外,還有幾點須要注意。


*轉移符\的使用,Python自己有轉移符,在Re模塊中也有轉移符,所以,若是在Re裏要匹配一個字符\,須要使用\\\\四次,首先Python轉移爲\\進入Re,而後Re再轉義成\;一個簡單的方法是使用原生字符r,這樣\\就好了。


例7

>>> a=re.findall('\\\\','\sabc')
print(a)
b=re.findall(r'\\','\sjkll')
print(b)
['\\']
['\\']


正則裏面有1個基本的概念叫作貪婪模式和懶惰模式。在上面的例子裏面,默認都是使用的貪婪模式,若是一個字符串裏面存在多個匹配,他默認用最長的那個;懶惰模式則是對應的最短的那個匹配。懶惰模式能夠經過*?或者+?或者 ??來實現。注意單獨使用的?表示前面那個字符的0或者1次匹配,可是組合在一塊兒就是懶惰模式了。


例8,這裏 .*? 至關於一個總體,.*表示任意值,而.*?表示任意值的懶惰匹配

import re
s1="hello Pythonssn"
pat="p.*n"
pat2="p.*?n"
r1=re.search(pat,s1,re.I)
r2=re.search(pat2,s1,re.I)
if r1:
    print(r1.group())
if r2:
    print(r2.group())
 ---------
Pythonssn
Python


第二個重要的概念是模式修飾符,能夠在不修改模式的狀況下實現一些額外的功能,常見的好比能夠進行多行匹配,忽略大小寫和用. 來替代換行符


例9

s2="""
python is funny,
Python is not PPython;
ppyhonn is Pyyon
"""
pat3="p.*?n"
pat4="p.*n"
r=re.findall(pat3,s2,re.I|re.M)
r2=re.findall(pat4,s2,re.I)
-------
['python', 'Python', 'PPython', 'ppyhon', 'Pyyon']
['python is funn', 'Python is not PPython', 'ppyhonn is Pyyon']


正則裏面還有有一個概念叫作分組。簡單的說,分組就是在已經匹配獲取的結果裏面繼續劃分新的子集。


在search和match裏面,group表明的是獲取經過pattern匹配出來的結果;groups表示分組以後的結果;groupdic一樣表示分組以後的結果,不過他須要經過P?指定名字才能顯示出來


例10

import re
a=re.search('h(?P<name>\w+)','hello 123a hoo bc333')
print(a.group())
print(a.groups())
print(a.groupdict())
----------------
hello
('ello',)
{'name': 'ello'}


在findall裏面分組比較特殊,若是有分組,那麼他直接就顯示出分組以後的子集,而不是匹配到的字符串


例9 首先匹配到['1hh','2kll']而後分組獲取數字後面部分

>>> import re
a=re.findall('\d(\w+)','1hh jjkl2 hhs 2kll')
print(a)
['hh', 'kll']


sub就是替換,不存在分組


split的分組以下所示


例11,對比一下不分組和分組的差異,前者分割以後不會出現分隔符,後者會顯示出來

>>> a='i am ha happy man'
print(re.split('am',a))
a='i am ha happy man'
print(re.split('(am)',a))
----------------
['i ', ' ha happy man']
['i ', 'am', ' ha happy man']


最後補充一下,正則表達式的函數除了能夠直接使用re.search, re.match等形式,還能夠先編譯一個pattern,而後經過pattern來調用這些函數


例12 先編譯一次正則表達式,而後再經過編譯後的pattern來調用,這樣若是調用的地方不少,能夠節省一下資源

>>> import re
>>> p=re.compile(r'\b\w+\b')
>>> match=p.search('jkl jkljl 23jk4 kjl2')
>>> print(match.group())
jkl
>>> p.findall('jkl kls 234lkjk23 23lk ')
['jkl', 'kls', '234lkjk23', '23lk']


最後,給出一些經常使用的組合方式


驗證數字:^[0-9]*$
驗證n位的數字:^\d{n}$
驗證至少n位數字:^\d{n,}$
驗證m-n位的數字:^\d{m,n}$
驗證零和非零開頭的數字:^(0|[1-9][0-9]*)$
驗證有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$
驗證有1-3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
驗證非零的正整數:^\+?[1-9][0-9]*$
驗證非零的負整數:^\-[1-9][0-9]*$
驗證非負整數(正整數 + 0)  ^\d+$
驗證非正整數(負整數 + 0)  ^((-\d+)|(0+))$
驗證長度爲3的字符:^.{3}$
驗證由26個英文字母組成的字符串:^[A-Za-z]+$
驗證由26個大寫英文字母組成的字符串:^[A-Z]+$
驗證由26個小寫英文字母組成的字符串:^[a-z]+$
驗證由數字和26個英文字母組成的字符串:^[A-Za-z0-9]+$
驗證由數字、26個英文字母或者下劃線組成的字符串:^\w+$
驗證用戶密碼:^[a-zA-Z]\w{5,17}$ 正確格式爲:以字母開頭,長度在6-18之間,只能包含字符、數字和下劃線。
驗證是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
驗證漢字:^[\u4e00-\u9fa5],{0,}$
驗證Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
驗證InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
驗證電話號碼:^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$:--正確格式爲:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
驗證身份證號(15位或18位數字):^\d{15}|\d{}18$
驗證一年的12個月:^(0?[1-9]|1[0-2])$ 正確格式爲:「01」-「09」和「1」「12」
驗證一個月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$    正確格式爲:0一、09和一、31。
整數:^-?\d+$
非負浮點數(正浮點數 + 0):^\d+(\.\d+)?$
正浮點數   ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮點數(負浮點數 + 0) ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
負浮點數  ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮點數  ^(-?\d+)(\.\d+)?$ 0 0 0 

相關文章
相關標籤/搜索