1. 正則表達式基礎html
1.1. 簡單介紹python
正則表達式並非Python的一部分。正則表達式是用於處理字符串的強大工具,擁有本身獨特的語法以及一個獨立的處理引擎,效率上可能不如str自帶的方法,但功能十分強大。得益於這一點,在提供了正則表達式的語言裏,正則表達式的語法都是同樣的,區別只在於不一樣的編程語言實現支持的語法數量不一樣;但不用擔憂,不被支持的語法一般是不經常使用的部分。若是已經在其餘語言裏使用過正則表達式,只須要簡單看一看就能夠上手了。正則表達式
下圖展現了使用正則表達式進行匹配的流程: http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
編程
正則表達式的大體匹配過程是:依次拿出表達式和文本中的字符比較,若是每個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。若是表達式中有量詞或邊界,這個過程會稍微有一些不一樣,但也是很好理解的,看下圖中的示例以及本身多使用幾回就能明白。編程語言
下圖列出了Python支持的正則表達式元字符和語法:工具
1.」.「匹配任意除換行符之外的字符編碼
>>> string = "abafsdafd\nafdasfd" #包含換行符
>>> string1 = "adfasdfadfasdfwer12345656耿" #不包含換行符
>>> import re
>>> m = re.search(".+",string) #驗證是否能夠匹配換行符
>>> m.group()
'abafsdafd'spa
>>> n = re.search(".+",string1)
>>> n.group()
'adfasdfadfasdfwer12345656耿'
從上面輸出結果能夠看出,」.「是匹配任意除了換行符的字符。遇到"\n"換行符即終止匹配。.net
2.」\"轉義字符code
轉義字符,使後一個字符改變原來的意思。若是字符串中有*號須要匹配,可使用\*或者字符集[*],"a\.c"表明匹配a.c "a\\c"表明匹配a\c
>>> str_num = "22.567979mafdasdf"
>>> m = re.search("\d+\.\d+",str_num)
>>> m.group()
'22.567979'
咱們知道,"."在python中表明的含義是除了"\n"以外的全部字符,若是這裏不進行轉義的話,匹配出來的就是任意非"\n"字符,所以要使用"\"進行轉義。
>>> string = "dfafdasfd\fafdasfda"
>>> string
'dfafdasfd\x0cafdasfda'
在python中,若是字符串中包含"\",有時候會顯示不出來,或者修改後面的內容,把別人改變了,這個不知道在Linux平臺上是怎麼回事。
3.[...]字符集(字符類)
[...]:字符集(字符類)對應的位置能夠是字符集中任意字符。字符集中的字符能夠逐個列出[0,1,2,3,4,5,6,7,8,9],也能夠給出範圍[0-9]。第一個字符集若是是^表示取反,如[^abc]表示不是abc的其餘字符。
全部的特殊字符在字符集中都失去其原有的特殊意義。在字符集中若是要使用]、或^,能夠在前面加上"\"反斜槓,或把]\、-放在第一個字符,把^放在非第一個字符。
>>> string = "dafdafdasf[adfas^fad"
>>> m = re.search("[a-z]+\[",string)
>>> m.group()
'dafdafdasf['
從上面腳本能夠看出,若是要匹配[要在前面加上"\"轉義字符。
>>> m = re.search("\w+[[]",string) (1)在字符集中匹配"["
>>> m.group()
'dafdafdasf['
>>> n = re.search("w+[\[]",string) (2)轉義匹配,驗證在字符集中匹配[是否須要加[\]
>>> n.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
在字符集中若是要使用]、或^,能夠在前面加上"\"反斜槓,或把]\、-放在第一個字符,把^放在非第一個字符。
預約義字符集
1.\d數字
>>> m = re.search("\d",string)
>>> m.group()
'1'
\d是匹配數字,等價於[0-9]
2.\D非數字 等價於[^\d]
>>> string = "dfaMNA12581耿fa"
>>> m = re.search("\D",string)
>>> m.group()
'd'
>>> n = re.search("[^\d]",string)
>>> n.group()
'd'
>>> l = re.search("[^0-9]",string)
>>> l.group()
'd'
從上面能夠看出,「\D」是用來匹配非數字的,匹配除了數字0-9意外的任意字符,等價於[^0-9]或[^\d]
3.\s空白字符 [<空格>\r\t\n\f\v]
「\s」是匹配任意非空字符,如[<空格>\r\t\n\f\v]等,實例以下:
>>> m = re.search("\s+",string) #\s進行匹配空白字符
>>> m.group()
' \t \n \x0c \x0b \r'
從上面能夠看出,\s是匹配任意空白字符,如空格、\r、\t、\n、\f、\v等
4.\S非空白字符 \S與\s正好相反,是匹配任意非空字符。等價於[^\s]匹配任意非空字符
>>> string = "faMM耿 \t \n \f \v \rDASDF"
>>> n = re.search("\S+",string)
>>> n.group()
'faMM耿'
從上面能夠看出"\S"是匹配任意非空字符,遇到空的字符即中止了,匹配任意非空字符,"."匹配任意字符,除了換行符以外。
>>> m = re.search(".+",string)
>>> m.group()
'faMM耿 \t '
從上面看出,「\S」和「.」仍是有差異的,一個是任意非空字符,一個是匹配任意除了"\n"意外任意非空字符。
5.\w 單詞字符[A-Z0-9a-z_]
\w是匹配單詞字符,下面來看下能不能匹配漢字或其餘:
>>> string = "faMM耿 \t \n \f \v \rDASDF"
>>> m = re.search("\w+",string)
>>> m.group()
'faMM耿' (1)腳本
>>> format_string = "fdMM更KKMM長 /大MM \n \tMMKDSI"
>>> m = re.search("\w+",format_string)
>>> m.group()
'fdMM更KKMM長' (2)腳本
能夠看出,"\w"是能夠匹配漢字的,不能匹配空格,換行符這些,可是可以匹配漢字。
6.\W 等價於非單詞字符 [^\w]
>>> import re
>>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
>>> m = re.search("\W+",string)
>>> m.group()
' '
從上面能夠看出"\W "匹配出來了空,說明" "不是單詞字符,"\W"是匹配非單詞字符。
數量詞(用在字符或(...)以後)
1."*" 匹配前一個字符0或無限次 前一個字符
"*"是匹配前一個字符0或無限次
>>> import re
>>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
>>> m = re.search("\w*",string)
>>> m.group()
'naefda曾'
>>> n = re.search("\d*",string)
>>> n.group()
''
>>> n = re.search("耿",string)
>>> n
>>> n.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
從上面腳本代碼能夠看出,當使用*要查找的字符在開頭的時候就會匹配到,在中間就匹配不到。這種懶惰的匹配方式,若是其餘狀況下匹配不到,則會返回錯誤。
2.「+」 匹配前一個字符一次或無限次 前一個字符(牢記,只是匹配前面一個)
>>> import re
>>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
>>> m = re.search("\w+",string)
>>> m.group()
'naefda曾'
>>> n = re.search("\s+",string)
>>> n.group()
' '
>>> d = re.search("更",string)
>>> d.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
從上面能夠看出,"+"是匹配前一個字符一次或無限次,若是匹配不到,則返回None
3."?" 匹配前一個字符0次或一次 前一個字符(牢記,只是匹配前面一個)
>>> import re
>>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
>>> m = re.search("\w?",string)
>>> m.group()
'n'
>>> n = re.search("f?",string)
>>> n.group()
''
從上面能夠看出,?是以貪婪的方式進行匹配。?是匹配前一個字符0次或1次。從上面的例子中發現一個問題,即"?"和"*"都是從頭開始進行匹配,若是開頭匹配不到,就返回"",等價於若是使用search()出現」?"和「*」等價於使用match()從頭開始匹配,找不到則不找了,不同的是match()返回的是None,而seach()返回的是""。
4.{m} 表明匹配前一個字符m次 前一個字符(牢記,只是匹配前面一個)
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> m = re.search("\d{4}",string) #表明匹配數字四次
>>> m.group()
'1134'
>>> n = re.search("\d{10}",string)
>>> n.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
從上面能夠看出,若是匹配不到,則返回None;{m}是表明匹配前一個字符m次,要注意在匹配的時候,咱們能夠像下面同樣設定一個匹配區間,這樣就不會出現匹配超標的狀況。
5.{m,n} 匹配一個字符m次至n次 前一個字符(牢記,只是匹配前面一個)
m和n能夠省略,如省略m({,n})則匹配0到n次;若省略n({m,}),則匹配m至無限次。
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> m = re.search("\d{1,10}",string)
>>> m.group()
'1134657'
>>> n = re.search("\d{,5}",string)
>>> n.group()
''
>>> d = re.search("\d{4,}",string)
>>> d.group()
'1134657'
從上面能夠看出,{m,n}是匹配在一個範圍內的個數,可是咱們也發現了一個問題,千萬不要讓正則表達式匹配包含0次的狀況,一旦匹配0次,那麼就會出現若是開頭匹配不到以後,就不匹配的狀況,直接返回""。
*? +? ?? {m,n}?使*,+,?,{m,n}變成非貪婪模式。
邊界匹配
1.^ 匹配字符串開頭,在多行模式中,匹配第一行的開頭
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> m = re.search("^da",string)
>>> m.group()
'da'
開頭匹配,至關於使用match()進行匹配了。
2.$ 匹配字符串末尾,在多行模式中匹配每一行的末尾
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> m = re.search("#!",string)
>>> m.group()
'#!'
"$"是匹配字符串的末尾,無論前面,值匹配末尾是不是要匹配的內容。
3.\A 僅匹配字符串開頭
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> m = re.search("\Adaf",string)
>>> m.group()
'daf'
「\A」是僅匹配字符串開頭,即僅僅從字符串的開頭進行匹配。
4.\Z 僅匹配字符串末尾
>>> import re
>>> string = "dafMM\n更1134657Qqcd m,l#!"
>>> n = re.search("l#!",string)
>>> n.group()
'l#!'
"\Z"是僅匹配字符串末尾,僅從末尾進行匹配,可能\Z和$的區別就是,$是匹配每行的末尾,而\Z是僅匹配字符串的末尾。
5.\b 匹配\w和\W之間的字符
6.\B 匹配非\w和\W之間的字符 即[^\b]
邏輯分組
1.「|」 表明左右表達式任意匹配一個
它老是先嚐試匹配左邊的表達式,一旦成功則跳過右邊的表達式。若是|沒有被包含在()中,則它的範圍是整個正則表達式
>>> import re
>>> m = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict()
>>> m
{'city': '81', 'birthday': '1993', 'province': '3714'}
能夠依次分組匹配,生成一個字典,groupdict(),分組匹配,給匹配到的字符串起名字。
1.2. 數量詞的貪婪模式與非貪婪模式
正則表達式一般用於在文本中查找匹配的字符串。Python裏數量詞默認是貪婪的(在少數語言裏也多是默認非貪婪),老是嘗試匹配儘量多的字符;非貪婪的則相反,老是嘗試匹配儘量少的字符。例如:正則表達式"ab*"若是用於查找"abbbc",將找到"abbb"。而若是使用非貪婪的數量詞"ab*?",將找到"a"。
1.3. 反斜槓的困擾
與大多數編程語言相同,正則表達式裏使用"\"做爲轉義字符,這就可能形成反斜槓困擾。假如你須要匹配文本中的字符"\",那麼使用編程語言表示的正則表達式裏將須要4個反斜槓"\\\\":前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓。Python裏的原生字符串很好地解決了這個問題,這個例子中的正則表達式可使用r"\\"表示。一樣,匹配一個數字的"\\d"能夠寫成r"\d"。有了原生字符串,你不再用擔憂是否是漏寫了反斜槓,寫出來的表達式也更直觀。
1.4. 匹配模式
正則表達式提供了一些可用的匹配模式,好比忽略大小寫、多行匹配等,這部份內容將在Pattern類的工廠方法re.compile(pattern[, flags])中一塊兒介紹。
2. re模塊
2.1. 開始使用re
Python經過re模塊提供對正則表達式的支持。使用re的通常步驟是先將正則表達式的字符串形式編譯爲Pattern實例,而後使用Pattern實例處理文本並得到匹配結果(一個Match實例),最後使用Match實例得到信息,進行其餘的操做。
import re #將正則表達式編譯成Pattern對象 pattern = re.compile(r'hello') #使用pattern匹配文本,得到匹配結果,沒法匹配時將返回None match = pattern.match("hello world!") if match: #使用match得到分組信息 print(match.group())
上面正則匹配中,首先進行了編譯,編譯成正則格式,而後進行匹配。
re.compile(strPattern[, flag]):
這個方法是Pattern類的工廠方法,用於將字符串形式的正則表達式編譯爲Pattern對象。 第二個參數flag是匹配模式,取值可使用按位或運算符'|'表示同時生效,好比re.I | re.M。另外,你也能夠在regex字符串中指定模式,好比re.compile('pattern', re.I | re.M)與re.compile('(?im)pattern')是等價的。
可選值有:
re模塊還提供了一個方法escape(string),用於將string中的正則表達式元字符如*/+/?等以前加上轉義符再返回,在須要大量匹配元字符時有那麼一點用。
2.2. Match
>>> string = "aafaaMMaaaa"
>>> m = re.search("aa?",string)
>>> m.group()
'aa'
>>> n = re.search("aaa?",string)
>>> n.group()
'aa'
>>> d = re.search("aaaa?",string)
>>> d.group()
'aaaa'
上面代碼中,"?"的做用是匹配前一個字符,就是這個正則符號前面的那個字符0次或一次。
正則表達式匹配中文(http://blog.csdn.net/tao_627/article/details/51019972)
import re
name = "ge耿長學164——///大師傅"
# name = name.encode('utf-8')
d = re.search(u"([\u4e00-\u9fa5]+)",name)
print(d.group())
unicode中中文的編碼爲/u4e00-/u9fa5
上面的正則表達式u"([\u4e00-\u9fa5]+)"就是用來匹配中文字符的,
匹配非中文字符集以下:
import re
name = "ge耿長學164——///大師傅"
# name = name.encode('utf-8')
d = re.search(u"([^\u4e00-\u9fa5]+)",name)
print(d.group())
只需在正則表達式裏面加上^,非的意思,就是匹配中文意外的其餘字符。