python 詳解正則表達式的使用(re模塊)

一,什麼是正則表達式       

     正則表達式(regular expression)描述了一種字符串匹配的模式(pattern),能夠用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等。java

    構造正則表達式的方法和建立數學表達式的方法同樣。也就是用多種元字符與運算符能夠將小的表達式結合在一塊兒來建立更大的表達式。正則表達式的組件能夠是單個的字符、字符集合、字符範圍、字符間的選擇或者全部這些組件的任意組合。python

     正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱爲"元字符")組成的文字模式。模式描述在搜索文本時要匹配的一個或多個字符串。正則表達式做爲一個模板,將某個字符模式與所搜索的字符串進行匹配。正則表達式

二,經常使用的正則匹配工具

在線匹配工具:sql

  1 http://www.regexpal.com/ express

       2 http://rubular.com/ 編程

     正則匹配軟件網絡

      McTracer   (https://pan.baidu.com/s/19Yn49)編程語言

      用過幾個以後仍是以爲這個是最好用的,支持將正則導成對應的語言如java C# js等還幫你轉義了,Copy直接用就好了很方便,另外支持把正則表達式用法解釋,如哪一段是捕獲分組,哪段是貪婪匹配等等,總之用起來很是好。函數

三,正則字符介紹

3.1普通字符

普通字符包括沒有顯式指定爲元字符的全部可打印和不可打印字符,這就包括了全部大寫和小寫字母,全部數字,全部標點符合和一些其餘字符。工具

字符 描述
"^" :^會匹配行或者字符串的起始位置,有時還會匹配整個文檔的起始位置。
"$" $會匹配行或字符串的結尾
"\b" 不會消耗任何字符只匹配一個位置,經常使用於匹配單詞邊界 如 我想從字符串中"This is Regex"匹配單獨的單詞 "is" 正則就要寫成 "\bis\b"  
"\d"

匹配數字,例如要匹配一個固定格式的電話號碼以0開頭前4位後7位,如0737-5686123  正則:^0\d\d\d-\d\d\d\d\d\d\d$ 

"\w"

匹配字母,數字,下劃線.例如我要匹配"a2345BCD__TTz" 正則:"\w+"  這裏的"+"字符爲一個量詞指重複的次數

"\s"

匹配空格      例如字符 "a b c" 正則:"\w\s\w\s\w"  一個字符後跟一個空格,若有字符間有多個空格直接把"\s" 寫成 "\s+" 讓空格重複

"." 匹配除了換行符之外的任何字符
"[abc]"

字符組  匹配包含括號內元素的字符         這個比較簡單了只匹配括號內存在的字符,還能夠寫成[a-z]匹配a至z的因此字母就等於能夠用來控制只能輸入英文了

 

 

 

3.2非打印字符

非打印字符也能夠是正則表達式的組成部分,下表列出了非打印字符的轉義序列:

字符  
 \cx 匹配由x指明的控制字符,例如,\cm匹配一個Control-M或回車符。x死亡值必須爲A~Z或者a~z之一,不然c被視爲一個原意的"c"字符
 \f 匹配一個換頁符,等價於\x0c和\cL
 \n 匹配一個換行符,等價於\x0a和\cJ
\r 匹配一個回車符,等價於\x0d和\cM
\s 匹配任何空白字符,包括空格,製表符,換頁符等等,等價於[\f\n\r\t\v]
\S 匹配任何非空字符,等價於[^\f\n\r\t\v]
\t 匹配一個製表符,等價於\x09和\cl
\v 匹配一個垂直製表符。等價於\x0b和\cK

3.3特殊字符

特殊字符就是一些有特殊含義的字符,簡單的說就是表示任何字符串的意思。若是要查找字符串的*符號,則須要對*進行轉義,即在前面加上一個\。

許多元字符要求在試圖匹配他們時特別對待,如果要匹配這些特殊字符,必須首先使字符轉義,即將反斜槓\放在他們前面。下表列出了正則表達式中的特殊字符。

特別字符 描述
$ 匹配輸入字符串的結尾位置.要匹配 $ 字符自己,請使用 \$。
() 標記一個子表達式的開始和結束位置。子表達式能夠獲取供之後使用。要匹配這些字符,請使用 \( 和 \)。
* 匹配前面的子表達式零次或屢次。要匹配 * 字符,請使用 \*。
+ 匹配前面的子表達式一次或屢次。要匹配 + 字符,請使用 \+。
. 匹配除換行符 \n 以外的任何單字符。要匹配 . ,請使用 \. 。
[ 標記一箇中括號表達式的開始。要匹配 [,請使用 \[。
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。
\ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符自己,請使用 \^。
{ 標記限定符表達式的開始。要匹配 {,請使用 \{。
| 指明兩項之間的一個選擇。要匹配 |,請使用 \|。

3.4限定符(懶惰限定符)

限定符用來指正則表達式的一個給定組件必需要出現多少次才能知足匹配,有*或+或?或{n}或{n,}或{n,m}六種。

字符 描述
* 匹配前面的子表達式零次或屢次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表達式一次或屢次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
匹配前面的子表達式零次或一次。例如,"do(es)?" 能夠匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等價於 {0,1}。
{n} n 是一個非負整數。匹配肯定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',可是能匹配 "food" 中的兩個 o。
{n,} n是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的全部 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。
{n,m} m 和 n 均爲非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。

3.5反義字符

寫法很簡單,就是字符改成大寫就好了,意思和原來相反。

字符 描述
\W 匹配任何不是字母數字,下劃線的字符
\S 匹配任何不是空白符的字符
\D 匹配任何非數字的字符
\B 匹配不是單詞開頭或結束的位置
[^abc] 匹配除了abc之外的任意字符

四,正則捕獲

    先了解在正則中捕獲分組的概念,其實就是一個括號內的內容 如 "(\d)\d" 而"(\d)" 這就是一個捕獲分組,能夠對捕獲分組進行 後向引用 (若是後而有相同的內容則能夠直接引用前面定義的捕獲組,以簡化表達式) 如(\d)\d\1 這裏的"\1"就是對"(\d)"的後向引用

那捕獲分組有什麼用呢看個例子就知道了

   如  "zery zery" 正則 \b(\w+)\b\s\1\b 因此這裏的"\1"所捕獲到的字符也是 與(\w+)同樣的"zery",爲了讓組名更有意義,組名是能夠自定義名字的

   "\b(?<name>\w+)\b\s\k<name>\b" 用"?<name>"就能夠自定義組名了而要後向引用組時要記得寫成 "\k<name>";自定義組名後,捕獲組中匹配到的值就會保存在定義的組名裏

下面列出捕獲分組常有的用法

字符 描述
(exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<name>exp) 匹配exp,並捕獲文本到名稱爲name的組裏
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
(?=exp)

匹配exp前面的位置

  如 "How are you doing" 正則"(?<txt>.+(?=ing))" 這裏取ing前全部的字符,並定義了一個捕獲分組名字爲 "txt" 而"txt"這個組裏的值爲"How are you do";

(?<=exp)

匹配exp後面的位置

  如 "How are you doing" 正則"(?<txt>(?<=How).+)" 這裏取"How"以後全部的字符,並定義了一個捕獲分組名字爲 "txt" 而"txt"這個組裏的值爲" are you doing";

(?!exp)

匹配後面跟的不是exp的位置

  如 "123abc" 正則 "\d{3}(?!\d)"匹配3位數字後非數字的結果

(?<!exp)

匹配前面不是exp的位置

  如 "abc123 " 正則 "(?<![0-9])123" 匹配"123"前面是非數字的結果也可寫成"(?!<\d)123"

 五,常見的正則表達式總結

非負整數:^\d+$

正整數:^[0-9]*[1-9][0-9]*$

非正整數:^((-\d+)|(0+))$

負整數:^-[0-9]*[1-9][0-9]*$

整數:^-?\d+$

非負浮點數:^\d+(\.\d+)?$

正浮點數 : ^((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+)?))$

負浮點數:^(-((正浮點數正則式)))$

英文字符串:^[A-Za-z]+$

英文大寫串:^[A-Z]+$

英文小寫串:^[a-z]+$

英文字符數字串:^[A-Za-z0-9]+$

英數字加下劃線串:^\w+$

E-mail地址:^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$

URL:^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$ 
或:^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$

郵政編碼:^[1-9]\d{5}$

中文:^[\u0391-\uFFE5]+$

電話號碼:^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$

手機號碼:^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$

雙字節字符(包括漢字在內):^\x00-\xff

匹配首尾空格:(^\s*)|(\s*$)(像vbscript那樣的trim函數)

匹配HTML標記:<(.*)>.*<\/\1>|<(.*) \/>

匹配空行:\n[\s| ]*\r

提取信息中的網絡連接:(h|H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?

提取信息中的郵件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

提取信息中的圖片連接:(s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?

提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+)

提取信息中的中國手機號碼:(86)*0*13\d{9}

提取信息中的中國固定電話號碼:(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}

提取信息中的中國電話號碼(包括移動和固定電話):(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}

提取信息中的中國郵政編碼:[1-9]{1}(\d+){5}

提取信息中的浮點數(即小數):(-?\d*)\.?\d+

提取信息中的任何數字 :(-?\d*)(\.\d+)? 

IP:(\d+)\.(\d+)\.(\d+)\.(\d+)

電話區號:/^0\d{2,3}$/

騰訊QQ號:^[1-9]*[1-9][0-9]*$

賬號(字母開頭,容許5-16字節,容許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

中文、英文、數字及下劃線:^[\u4e00-\u9fa5_a-zA-Z0-9]+$

匹配中文字符的正則表達式: [\u4e00-\u9fa5]

匹配雙字節字符(包括漢字在內):[^\x00-\xff]

匹配空行的正則表達式:\n[\s| ]*\r

匹配HTML標記的正則表達式:/<(.*)>.*<\/\1>|<(.*) \/>/

sql語句:^(select|drop|delete|create|update|insert).*$

匹配首尾空格的正則表達式:(^\s*)|(\s*$)

匹配Email地址的正則表達式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

  

5.1總結經常使用的正則表達式(表格形式)

'.'     默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
'^'     匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$'     匹配字符結尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也能夠
'*'     匹配*號前的字符0次或屢次,re.findall("ab*","cabb3abcbbac")  結果爲['abb', 'ab', 'a']
'+'     匹配前一個字符1次或屢次,re.findall("ab+","ab+cd+abb+bba") 結果['ab', 'abb']
'?'     匹配前一個字符1次或0次
'{m}'   匹配前一個字符m次
'{n,m}' 匹配前一個字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結果'ABC'
'(...)' 分組匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 結果 abcabca456c
 
 
'\A'    只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z'    匹配字符結尾,同$
'\d'    匹配數字0-9
'\D'    匹配非數字
'\w'    匹配[A-Za-z0-9]
'\W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 結果 '\t'
 
'(?P<name>...)' 分組匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})
(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
 結果{'province': '3714', 'city': '81', 'birthday': '1993'}

5.2 最經常使用的匹配語法

re.match 從頭開始匹配
re.search 匹配包含
re.findall 把全部匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符當作列表分隔符
re.sub      匹配字符並替換

 問題:反斜槓的困擾

  與大多數編程語言相同,正則表達式裏面使用「 \ 」做爲轉義字符,這就可能形成反斜槓困擾,假如你須要匹配文本中的字符'' \ '' 那麼使用編程語言表示的正則表達式裏面將須要4個反斜槓"\\\\",前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏面轉義成一個反斜槓,python裏的原生字符串很好的解決了這個問題,這個例子中的正則表達式可使用  r"\\  表示。一樣,匹配一個數字的"\\d"能夠寫成r"\d.有了原生字符串,你不再用擔憂是否是漏寫了反斜槓,寫出來的表達式也更直觀。

僅僅須要知道及格匹配模式

re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同)
M(MULTILINE): 多行模式,改變'^'和'$'的行爲(參見上圖)
S(DOTALL): 點任意匹配模式,改變'.'的行爲

  

六,re模塊

  就本質而言,正則表達式是一種小型的,高度專業化的編程語言,(在Python中)它內嵌在Python中,並經過 re 模塊實現。正則表達式模式被編譯成一系列的字節碼,而後由用 C 編寫的匹配引擎執行。

   字符匹配(普通字符和元字符)

1 普通字符:大多數字符和字母都會和自身匹配
              >>> re.findall('alvin','yuanaleSxalexwupeiqi')
                      ['alvin'] 

2 元字符:. ^ $ * + ? { } [ ] | ( ) \

  

元字符.^$*+?{}

import re
 
ret=re.findall('a..in','helloalvin')
print(ret)#['alvin']
 
 
ret=re.findall('^a...n','alvinhelloawwwn')
print(ret)#['alvin']
 
 
ret=re.findall('a...n$','alvinhelloawwwn')
print(ret)#['awwwn']
 
 
ret=re.findall('a...n$','alvinhelloawwwn')
print(ret)#['awwwn']
 
 
ret=re.findall('abc*','abcccc')#貪婪匹配[0,+oo]  
print(ret)#['abcccc']
 
ret=re.findall('abc+','abccc')#[1,+oo]
print(ret)#['abccc']
 
ret=re.findall('abc?','abccc')#[0,1]
print(ret)#['abc']
 
 
ret=re.findall('abc{1,4}','abccc')
print(ret)#['abccc'] 貪婪匹配

  

注意:前面的*,+,?等都是貪婪匹配,也就是儘量匹配,後面加?號使其變成惰性匹配

ret=re.findall('abc*?','abcccccc')
print(ret)#['ab']

  

元字符之字符集[]:

#--------------------------------------------字符集[]
ret=re.findall('a[bc]d','acd')
print(ret)#['acd']
 
ret=re.findall('[a-z]','acd')
print(ret)#['a', 'c', 'd']
 
ret=re.findall('[.*+]','a.cd+')
print(ret)#['.', '+']
 
#在字符集裏有功能的符號: - ^ \
 
ret=re.findall('[1-9]','45dha3')
print(ret)#['4', '5', '3']
 
ret=re.findall('[^ab]','45bdha3')
print(ret)#['4', '5', 'd', 'h', '3']
 
ret=re.findall('[\d]','45bdha3')
print(ret)#['4', '5', '3']

  

元字符之轉義符\

反斜槓後邊跟元字符去除特殊功能,好比\.
反斜槓後邊跟普通字符實現特殊功能,好比\d

\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  匹配一個特殊字符邊界,好比空格 ,&,#等

  

ret=re.findall('I\b','I am LIST')
print(ret)#[]
ret=re.findall(r'I\b','I am LIST')
print(ret)#['I']

  

如今咱們聊一聊\,先看下面兩個匹配:

#-----------------------------eg1:
import re
ret=re.findall('c\l','abc\le')
print(ret)#[]
ret=re.findall('c\\l','abc\le')
print(ret)#[]
ret=re.findall('c\\\\l','abc\le')
print(ret)#['c\\l']
ret=re.findall(r'c\\l','abc\le')
print(ret)#['c\\l']
 
#-----------------------------eg2:
#之因此選擇\b是由於\b在ASCII表中是有意義的
m = re.findall('\bblow', 'blow')
print(m)
m = re.findall(r'\bblow', 'blow')
print(m)

  

元字符之分組()

m = re.findall(r'(ad)+', 'add')
print(m)
 
ret=re.search('(?P<id>\d{2})/(?P<name>\w{3})','23/com')
print(ret.group())#23/com
print(ret.group('id'))#23

元字符之|

ret=re.search('(ab)|\d','rabhdg8sd')
print(ret.group())#ab

re模塊下的經常使用方法

import re
#1
re.findall('a','alvin yuan')   
 #返回全部知足匹配條件的結果,放在列表裏
#2
re.search('a','alvin yuan').group() 
 #函數會在字符串內查找模式匹配,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠
  # 經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。
 
#3
re.match('a','abc').group()     
#同search,不過盡在字符串開始處進行匹配
 
#4
ret=re.split('[ab]','abcd')     
#先按'a'分割獲得''和'bcd',在對''和'bcd'分別按'b'分割
print(ret)#['', '', 'cd']
 
#5
ret=re.sub('\d','abc','alvin5yuan6',1)
print(ret)#alvinabcyuan6
ret=re.subn('\d','abc','alvin5yuan6')
print(ret)#('alvinabcyuanabc', 2)
 
#6
obj=re.compile('\d{3}')
ret=obj.search('abc123eeee')
print(ret.group())#123

  

import re
ret=re.finditer('\d','ds3sy4784a')
print(ret)        #<callable_iterator object at 0x10195f940>
 
print(next(ret).group())
print(next(ret).group())

  

注意:

import re
 
ret=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
print(ret)#['oldboy']     這是由於findall會優先把匹配結果組裏內容返回,若是想要匹配結果,取消權限便可
 
ret=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
print(ret)#['www.oldboy.com']

  

import re

print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>"))

  

#匹配出全部的整數
import re

#ret=re.findall(r"\d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
ret.remove("")

print(ret)

  再來一張圖:

 

那兩張圖來自:https://blog.csdn.net/xujin0/article/details/83312406

相關文章
相關標籤/搜索