一.正則表達式中常用元字符的復習。

通配符系列

.(點)匹配任意一個除換行符以外的字符。

*(星號)用來匹配*星號前面的字符或者一組字符0到無窮次。可以寫為0

+(加號)匹配加號前面的一個字符或者一組字符1到無窮次。可以寫為1

?(問號)匹配問號前面的一個字符或者一組字符0到1次。可以寫為 01

{n,m}(大括號):前面的一個字符或者一組字符至少匹配n次最多匹配m次。

{n}(大括號)只匹配n次。

{n,}:至少匹配n次。


字符集系列

[abcd1234]中括號中括號在正則表達式中就是一個字符集的功能用于匹配中括號內的任意一個字符。

例1

print re.findall(r'[abcd1234]','abcdefg1234567')

輸出匹配到的結果

['a', 'b', 'c', 'd', '1', '2', '3', '4']


減號或者叫橫線在中括號字符集中是有特殊意義的用于指一個字符串的范圍。

[a-z] : 代表一個所有的小寫字母。

[0-9]代表0-9的所有數字。

[a-Z]代表所有小寫和大寫字母。


^(尖號)在中括號字符集中也是有特殊意義的用于字符集取反下面是例子。

^a:匹配一個不為a的任意字符。

^a-z:代表不為所有小寫字母的任意字符。

?^0-9:代表不為所有數字的任意字符。

!!注意!! .(點) ?+(加號) ?*(星號) ,(逗號) 這幾個符號在[ ]中括號字符集中沒有任何特殊意義都會被當作普通字符來處理。

-(減號)^(尖號)\(反斜杠) ?這三個符號在中括號字符集中是具有特殊意義的減號則用于指定一個一個字符集的范圍反斜杠依舊有轉義符的作用比如d是一個普通字符\d就代表了數字0-9.

print re.findall(r'[\d]','abcdef\dg1234567')

匹配結果

['1', '2', '3', '4', '5', '6', '7']


開頭和結尾

^尖號匹配以一串字符串或者一個字符串開頭的字符。

$dollar匹配以一串字符串結尾或者一個字符串結尾的字符。



關于分組

()小括號用于分組。

首先來說說分組可以來實現什么功能吧

我們拿通配符加號來舉個例子

加號默認情況下只能匹配加號前面的字符1次到多次。

print re.findall(r'ab+','abbbbbbcdef\dg1234567')

輸出匹配結果

['abbbbbb']

前面的b被匹配了1到多次。


那么現在有一個需求就是把ab作為一組字符串ab這兩個字符當作一個整體重復匹配1到多次。

這個時候就需要用到小括號來實現分組功能。

print re.findall(r'(ab)+','abbbbbbcdef\dg1234567')

輸出匹配結果

['ab']

從結果可以看出ab這兩個字符被當作了一個整體去匹配。

如果覺得這個例子還不夠醒目不夠明顯可以看下面這個例子。

print re.findall(r'(ab)+haozhi','ababhaozhi')

輸出匹配結果

['ab']?

從上面這個例子說明了使用小括號分組之后被分組的表達式在findall方法中會被優先顯示出來小括號內中分組的正則表達式會被顯示小括號外的正則表達式也會去匹配只不過默認不顯示而已.(注意只有在使用findall方法才回出現這種情況)


其實findall方法的這個特性可以理解為按照一個條件去匹配內容但是只想顯示所匹配到的內容的一部分。這種功能可以使用findall這個方法結合分組特性去實現。

例如

現在需要找到“123asas456zzz765ayu”這串字符串中ayu前面的三位數。

print re.findall(r'(\d{3})ayu','123asas456zzz765ayu')????

\d 代表一個數字的字符集0-9重復匹配三次也就是說這是個三位數然后將其分組只匹配到三位數還不能滿足要求后面緊跟著ayu。

輸出匹配結果

['765']

這就是分組的優先級特性只顯示分組中的內容。


那么如何取消這種分組的優先級特性呢

想取消find方法中的這種分組優先級特性只需要在()小括號中加上一個?: 問號和冒號這種分組優先級特性就被取消了。

print re.findall(r'(?:\d{3})ayu','123asas456zzz765ayu')

輸出匹配結果

['765ayu']


豎線或管道符一般用在小括號分組中用來做一個或運算下面是個例子。

print re.findall("^www.(aaa|bbb).com$","www.bbb.com")

輸出結果

['bbb']

上面這個例子沒有取消分組優先的特性接下來將分組優先特性取消一下看看最原本的結果。

print re.findall("^www.(?:aaa|bbb).com$","www.bbb.com")

輸出結果

['www.bbb.com']


關于\反斜杠的補充

當\反斜杠后面加上了元字符就可以去掉元字符的特殊功能使其變成一個普通的字符串。

例如

\. ?\* \+ 等......

當反斜杠后面加一些普通字符后可以實現一些特殊功能。

\d :用于匹配所有十進制的數相當于0-9。

\D:用于匹配所有非數字字符相當于^0-9。

\s:用于匹配所有的空白字符相當于[\t\n\r\f\v]。

\S:用于匹配所有的非空白字符相當于[^\t\n\r\f\v]。

\w:用于匹配任何是數字或者字母或者下劃線的字符。相當于[a-zA-Z0-9_]。

\W:用于匹配任何非數字字母下劃線的字符。相當于[^a-zA-Z0-9_]。

\b:用來匹配一個特殊字符邊界比如空格 ?逗號 ?&and 井號。



不常用的知識點

貪婪匹配與非貪婪匹配:

在正則中,默認遵循的就是一種貪婪匹配原則(也可以說是最大匹配,或者說盡可能的最多匹配)。

非貪婪模式就是指按照最小的范圍進行匹配(盡可能的少匹配)。

這兩種模式是可以切換的,請看下面的例子:

#\d匹配所有的十進制數字,+加號代表匹配一次到n次,按照正則表達式默認的匹配原則,就是貪婪匹配,加號既然最多可以匹配無限次,那么有多少數字,全部都會被匹配到。

print re.findall("\d+","as121323jh1213232321hgj12132323")

輸出匹配結果:

['121323', '1213232321', '12132323']

那么如何切換到非貪婪模式匹配呢?只需要在通配符后面加上一個?問號,這個通配符就會啟用惰性匹配(非貪婪匹配)

print re.findall("\d+?","as121323jh1213232321hgj12132323")

輸出匹配結果:

['1', '2', '1', '3', '2', '3', '1', '2', '1', '3', '2', '3', '2', '3', '2', '1', '1', '2', '1', '3', '2', '3', '2', '3']

#+加號最小能匹配1個前面的字符或者字符串分組,非貪婪匹配就是指通配符的一個最小匹配,所以一次只匹配到了一個數字。





二.re模塊的常用方法

re.findall() 用于返回一個字符串中所有能被正則表達式所匹配到的字符串以列表的方式返回。

用法re.findall(正則表達式字符串)。

s1 = "sadjhjafdsajkhjsdaysadsadduayu"

比如說想要從上面這一長串字符串中匹配出a后面有一個任一字符在緊接著一個字母u的字符串。

print re.findall('a.u',s1)

>>>['ayu']


re.finditer()作用和findall一樣不過finditer返回的并不是個列表而是個迭代器對象如果需要迭代操作推薦使用finditer方法。


re.search() 在字符串中按照正則表達式去查找匹配所需要的字符串只找第一個匹配到的結果然后返回一個match對象這個對象中包含了通過正則表達式匹配的信息我們可以通過執行該對象.group方法去獲取所匹配到的字符串如果找到想匹配的字符串就回返回一個None。

用法re.search(正則表達式,字符串,flag)

s1 = "hamasaki ayumi"

print re.search('a.u',s1).group()

>>>ayu

re.match()字符串中按照正則表達式去查找匹配所需要的字符串,和search不同的是match只會從字符串的開頭進行匹配如果字符串開始不符合正則表達式則匹配失敗

用法和search是一樣的。


re.split()按照指定的正則表達式去拆分字符串。

以所有的字符串做為分隔符。

s = "a1b2c3d4e5"

print re.split(r'\d',s)

>>>['a', 'b', 'c', 'd', 'e', '']


re.sub()替換使用正則表達式匹配出字符串中的指定內容然后將其替換成指定的字符串。

s = "a1b2c3d4e5"

print re.sub(r'[a-z]','ayu',s)

>>>ayu1ayu2ayu3ayu4ayu5

re.sub()函數還有個參數可以設置替換多少次。

比如說只想替換前三個匹配到的。

s = "a1b2c3d4e5"

print re.sub(r'[a-z]','ayu',s,3)

>>>ayu1ayu2ayu3d4e5


re.subn() 和sub一樣都是通過正則來替換字符串內容的功能但是subn會返回一個元組這個元組里不單單只有替換后的字符串還包含了這個字符串中的內容被替換了幾次。

例如

s = "a1b2c3d4e5"

print re.subn(r'[a-z]','ayu',s)

>>>('ayu1ayu2ayu3ayu4ayu5', 5)


re.compile() 編譯可以把正則表達式編譯成一個正則表達式對象。可以把那些經常使用的正則表達式編譯成正則表達式對象這樣可以提高一定的效率。


re.match():功能和search有點像,但是最大的不同是,match只能從字符串的開頭處進行匹配。


二.python正則表達式之分組(無命名和有命名分組的補充 )。

python中正則常用的分組方式大概分為兩種。

方法1

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(0)

>>>010-123456

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(1)

>>>010

print re.search(r'(^\d{3,4})-(\d{3,8})','010-123456').group(2)

>>>123456

如果正則表達式中定義了組就可以在Match對象上用group()方法提取出子串。?

注意到group(0)永遠是原始字符串group(1)、group(2)……表示第1、2、……個子串。


方法2:

命名分組

print re.search(r'(?P<zone_num>^\d{3,4})-(?P<phone_num>\d{3,8})','010-123456').group("zone_num")

>>>010

print re.search(r'(?P<zone_num>^\d{3,4})-(?P<phone_num>\d{3,8})','010-123456').group("phone_num")

>>>123456