詳盡解讀正則表達式:python下的re方法

版權聲明:本文爲博主原創文章,歡迎交流分享,未經博主允許不得轉載。 https://blog.csdn.net/HHTNAN/article/details/84651583

關於正則表達式

正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。在很多文本編輯器裏,正則表達式通常被用來檢索、替換那些匹配某個模式的文本。

許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達式通常縮寫成“regex”,單數有regexp、regex,複數有regexps、regexes、regexen。

Python下的正則(regex)

可能對於Pythoner來說,一般提到正則就會馬上想到re模塊,其實我們通常處理正則都是處理字符串,字符串本身是有一些方法可以代替正則的,當然會在後面介紹re模塊,首先我們來看看字符串的操作。

正則表達式處理字符串主要有四大功能

-1. 匹配 查看一個字符串是否符合正則表達式的語法,一般返回true或者false

-2. 獲取 正則表達式來提取字符串中符合要求的文本

-3. 替換 查找字符串中符合正則表達式的文本,並用相應的字符串替換

-4. 分割 使用正則表達式對字符串進行分割。

1、字符串操作

1.1查找字符串

str.index 和str.find 功能相同,區別在於find()查找失敗會返回-1,存在返回對應索引,不會影響程序運行。一般用find!=-1或者find>-1來作爲判斷條件。index()不存在會報錯

#str.index:檢測字符串中是否包含子字符串str,可指定範圍
a='zero one'
a.index("r") 
2
a.index('x')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-51f0d5bb66b2> in <module>()
----> 1 a.index('x')
ValueError: substring not found
a.find('r')
2
#不存在返回-1
a.find('x')
-1

1.2是否包含指定字符串

in |not in

"zero" in a
True
"123" not in a
True

1.3字符串的測試、判斷函數,

字符串的測試、判斷函數,這一類函數在string模塊中沒有,這些函數返回的都是bool值

"""
    S.startswith(prefix[,start[,end]]) #是否以prefix開頭 
    S.endswith(suffix[,start[,end]]) #以suffix結尾 
    S.isalnum()    #是否全是字母和數字,並至少有一個字符 
    S.isalpha()    #是否全是字母,並至少有一個字符 
    S.isdigit()    #是否全是數字,並至少有一個字符 
    S.isspace()    #是否全是空白字符,並至少有一個字符 
    S.islower()    #S中的字母是否全是小寫 
    S.isupper()    #S中的字母是否便是大寫 
    S.istitle()    #S是否是首字母大寫的
"""
a.startswith("z")
True

2. 正則表達式語法

2.1 字符與字符類

1 特殊字符:.^$?+*{}|

以上特殊字符要想使用字面值,必須使用\進行轉義

     如果你想查找元字符本身的話,比如你查找.,或者*,就出現了問題:你沒辦法指定它們,因爲它們會被解釋成別的意思。這時你就得使用\來取消這些字符的特殊意義。因此,你應該使用\.和\*。當然,要查找\本身,你也得用\\.

例如:deerchao.net匹配deerchao.net,C:\Windows匹配C:\Windows。

2 字符類

1. 包含在[]中的一個或者多個字符被稱爲字符類,字符類在匹配時如果沒有指定量詞則只會匹配其中的一個。

2. 字符類內可以指定範圍,比如[a-zA-Z0-9]表示a到z,A到Z,0到9之間的任何一個字符

3. 左方括號後跟隨一個,表示否定一個字符類,比如[0-9]表示可以匹配一個任意非數字的字符。

4. 字符類內部,除了\之外,其他特殊字符不再具備特殊意義,都表示字面值。放在第一個位置表示否定,放在其他位置表示本身,-放在中間表示範圍,放在字符類中的第一個字符,則表示-本身。

5. 字符類內部可以使用速記法,比如\d \s \w

3 速記法

. 可以匹配除換行符之外的任何字符,如果有re.DOTALL標誌,則匹配任意字符包括換行

\d 匹配一個Unicode數字,如果帶re.ASCII,則匹配0-9

\D 匹配Unicode非數字

\s 匹配Unicode空白,如果帶有re.ASCII,則匹配\t\n\r\f\v中的一個

\S 匹配Unicode非空白

\w 匹配Unicode單詞字符,如果帶有re.ascii,則匹配[a-zA-Z0-9_]中的一個

\W 匹配Unicode非單子字符

2.2 量詞(匹配次數)

  1. ? 匹配前面的字符0次或1次

    • 匹配前面的字符0次或多次
    • 匹配前面的字符1次或者多次
  2. {m} 匹配前面表達式m次

  3. {m,} 匹配前面表達式至少m次

  4. {,n} 匹配前面的正則表達式最多n次

  5. {m,n} 匹配前面的正則表達式至少m次,最多n次

注意點:以上量詞都是貪婪模式,會儘可能多的匹配,如果要改爲非貪婪模式,通過在量詞後面跟隨一個?來實現,貪婪表示會盡可以多的匹配符合條件的字符,非貪婪則爲儘可以少的匹配。

2.3分枝條件

表達式也能匹配010)12345678或(022-87654321這樣的“不正確”的格式。要解決這個問題,我們需要用到分枝條件。正則表達式裏的分枝條件指的是有幾種規則,如果滿足其中任意一種規則都應該當成匹配,具體方法是用|把不同的規則分隔開。聽不明白?沒關係,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7}這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)。

(0\d{2})[- ]?\d{8}|0\d{2}[- ]?\d{8}這個表達式匹配3位區號的電話號碼,其中區號可以用小括號括起來,也可以不用,區號與本地號間可以用連字號或空格間隔,也可以沒有間隔。你可以試試用分枝條件把這個表達式擴展成也支持4位區號的。

\d{5}-\d{4}|\d{5}這個表達式用於匹配美國的郵政編碼。美國郵編的規則是5位數字,或者用連字號間隔的9位數字。

之所以要給出這個例子是因爲它能說明一個問題:使用分枝條件時,要注意各個條件的順序。如果你把它改成\d{5}|\d{5}-\d{4}的話,那麼就只會匹配5位的郵編(以及9位郵編的前5位)。原因是匹配分枝條件時,將會從左到右地測試每個條件,如果滿足了某個分枝的話,就不會去再管其它的條件了。

2.4分組

我們已經提到了怎麼重複單個字符(直接在字符後面加上限定符就行了);但如果想要重複多個字符又該怎麼辦?你可以用小括號來指定子表達式(也叫做分組),然後你就可以指定這個子表達式的重複次數了,你也可以對子表達式進行其它一些操作(後面會有介紹)。

(\d{1,3}.){3}\d{1,3}是一個簡單的IP地址匹配表達式。要理解這個表達式,請按下列順序分析它:\d{1,3}匹配1到3位的數字,(\d{1,3}.){3}匹配三位數字加上一個英文句號(這個整體也就是這個分組)重複3次,最後再加上一個一到三位的數字(\d{1,3})。

不幸的是,它也將匹配256.300.888.999這種不可能存在的IP地址。如果能使用算術比較的話,或許能簡單地解決這個問題,但是正則表達式中並不提供關於數學的任何功能,所以只能使用冗長的分組,選擇,字符類來描述一個正確的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。

理解這個表達式的關鍵是理解2[0-4]\d|25[0-5]|[01]?\d\d?,這裏我就不細說了,你自己應該能分析得出來它的意義。

小貼士:
IP地址中每個數字都不能大於255. 經常有人問我, 01.02.03.04 這樣前面帶有0的數字, 是不是正確的IP地址呢? 答案是: 是的, IP 地址裏的數字可以包含有前導 0 (leading zeroes).

2.5後向引用

使用小括號指定一個子表達式後,匹配這個子表達式的文本(也就是此分組捕獲的內容)可以在表達式或其它程序中作進一步的處理。默認情況下,每個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。

後向引用用於重複搜索前面某個分組匹配的文本。例如,\1代表分組1匹配的文本。難以理解?請看示例:

\b(\w+)\b\s+\1\b可以用來匹配重複的單詞,像go go, 或者kitty kitty。這個表達式首先是一個單詞,也就是單詞開始處和結束處之間的多於一個的字母或數字(\b(\w+)\b),這個單詞會被捕獲到編號爲1的分組中,然後是1個或幾個空白符(\s+),最後是分組1中捕獲的內容(也就是前面匹配的那個單詞)(\1)。

你也可以自己指定子表達式的組名。要指定一個子表達式的組名,請使用這樣的語法:(?\w+)(或者把尖括號換成’也行:(?‘Word’\w+)),這樣就把\w+的組名指定爲Word了。要反向引用這個分組捕獲的內容,你可以使用\k,所以上一個例子也可以寫成這樣:\b(?\w+)\b\s+\k\b。

使用小括號的時候,還有很多特定用途的語法。下面列出了最常用的一些
在這裏插入圖片描述
小貼士:
組號分配還不像我剛說得那麼簡單:

分組0對應整個正則表達式
實際上組號分配過程是要從左向右掃描兩遍的:第一遍只給未命名組分配,第二遍只給命名組分配--因此所有命名組的組號都大於未命名的組號
你可以使用(?:exp)這樣的語法來剝奪一個分組對組號分配的參與權.

2.6零寬斷言

接下來的四個用於查找在某些內容(但並不包括這些內容)之前或之後的東西,也就是說它們像\b,^,$那樣用於指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱爲零寬斷言。最好還是拿例子來說明吧:

(?=exp)也叫零寬度正預測先行斷言,它斷言自身出現的位置的後面能匹配表達式exp。比如\b\w+(?=ing\b),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I’m singing while you’re dancing.時,它會匹配sing和danc。

(?<=exp)也叫零寬度正回顧後發斷言,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的後半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。

假如你想要給一個很長的數字中每三位間加一個逗號(當然是從右邊加起了),你可以這樣查找需要在前面和裏面添加逗號的部分:((?<=\d)\d{3})+\b,用它對1234567890進行查找時結果是234567890。

下面這個例子同時使用了這兩種斷言:(?<=\s)\d+(?=\s)匹配以空白符間隔的數字(再次強調,不包括這些空白符)。

小貼士:
斷言用來聲明一個應該爲真的事實。正則表達式中只有當斷言爲真時纔會繼續進行匹配。

2.7 條件匹配

(?(id)yes_exp|no_exp):對應id的子表達式如果匹配到內容,則這裏匹配yes_exp,否則匹配no_exp

2.8 正則表達式的標誌

1. 正則表達式的標誌有兩種使用方法

1. 通過給compile方法傳入標誌參數,多個標誌使用|分割的方法,如re.compile(r"#[\da-f]{6}\b", re.IGNORECASE|re.MULTILINE)

2. 通過在正則表達式前面添加(?標誌)的方法給正則表達式添加標誌,如(?ms)#[\da-z]{6}\b

2. 常用的標誌

re.A或者re.ASCII, 使\b \B \s \S \w \W \d \D都假定字符串爲假定字符串爲ASCII

re.I或者re.IGNORECASE 使正則表達式忽略大小寫
     
re.M或者re.MULTILINE 多行匹配,使每個^在每個回車後,每個$在每個回車前匹配

re.S或者re.DOTALL 使.能匹配任意字符,包括回車

re.X或者re.VERBOSE 這樣可以在正則表達式跨越多行,也可以添加註釋,但是空白需要使用\s或者[ ]來表示,因爲默認的空白不再解釋。如:

    re.compile(r"""
          <img\s +)	#標籤的開始
          [^>]*?	#不是src的屬性
          src=	#src屬性的開始
          (?:
          (?P<quote>["'])	#左引號
          (?P<image_name>[^\1>]+?)	#圖片名字
          (?P=quote)	#右括號
          """,re.VERBOSE|re.IGNORECASE)

3.Python下的表達式

3.1Python中re模塊使用正則表達式的兩種方法

1. 使用re.compile(r, f)方法生成正則表達式對象,然後調用正則表達式對象的相應方法。好處》正則對象之後可以多次使用。

2. re模塊中對正則表達式對象的每個對象方法都有一個對應的模塊方法,唯一不同的是傳入的第一個參數是正則表達式字符串。此種方法適合於只》使用一次的正則表達式。

3.2 正則表達式對象的常用方法

  1. rx.findall(s,start, end):

返回一個列表,如果正則表達式中沒有分組,則列表中包含的是所有匹配的內容,

如果正則表達式中有分組,則列表中的每個元素是一個元組,元組中包含子分組中匹配到的內容,但是沒有返回整個正則表達式匹配的內容
2. rx.finditer(s, start, end):

返回一個可迭代對象

對可迭代對象進行迭代,每一次返回一個匹配對象,可以調用匹配對象的group()方法查看指定組匹配到的內容,0表示整個正則表達式匹配到的內容
3. rx.search(s, start, end):

返回一個匹配對象,倘若沒匹配到,就返回None

search方法只匹配一次就停止,不會繼續往後匹配
4. rx.match(s, start, end):

如果正則表達式在字符串的起始處匹配,就返回一個匹配對象,否則返回None

re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字符串,直到找到一個匹配。
5. rx.sub(x, s, m):

返回一個字符串。每一個匹配的地方用x進行替換,返回替換後的字符串,如果指定m,則最多替換m次。對於x可以使用/i或者/gid可以是組名或者編號來引用捕獲到的內容。

模塊方法re.sub(r, x, s, m)中的x可以使用一個函數。此時我們就可以對捕獲到的內容推過這個函數進行處理後再替換匹配到的文本。
6. rx.subn(x, s, m):

與re.sub()方法相同,區別在於返回的是二元組,其中一項是結果字符串,一項是做替換的個數。
7. rx.split(s, m):分割字符串

返回一個列表

用正則表達式匹配到的內容對字符串進行分割

如果正則表達式中存在分組,則把分組匹配到的內容放在列表中每兩個分割的中間作爲列表的一部分,如:

  rx = re.compile(r"(\d)[a-z]+(\d)")
  s = "ab12dk3klj8jk9jks5"
  result = rx.split(s)

返回[‘ab1’, ‘2’, ‘3’, ‘klj’, ‘8’, ‘9’, ‘jks5’]
8. rx.flags():正則表達式編譯時設置的標誌

  1. rx.pattern():正則表達式編譯時使用的字符串

3.3 匹配對象的屬性與方法

  1. m.group(g, …)
    返回編號或者組名匹配到的內容,默認或者0表示整個表達式匹配到的內容,如果指定多個,就返回一個元組
  2. m.groupdict(default)
    返回一個字典。字典的鍵是所有命名的組的組名,值爲命名組捕獲到的內容
    如果有default參數,則將其作爲那些沒有參與匹配的組的默認值。
  3. m.groups(default)
    返回一個元組。包含所有捕獲到內容的子分組,從1開始,如果指定了default值,則這個值作爲那些沒有捕獲到內容的組的值
  4. m.lastgroup()
    匹配到內容的編號最高的捕獲組的名稱,如果沒有或者沒有使用名稱則返回None(不常用)
  5. m.lastindex()
    匹配到內容的編號最高的捕獲組的編號,如果沒有就返回None。
  6. m.start(g):
    當前匹配對象的子分組是從字符串的那個位置開始匹配的,如果當前組沒有參與匹配就返回-1
  7. m.end(g)
    當前匹配對象的子分組是從字符串的那個位置匹配結束的,如果當前組沒有參與匹配就返回-1
  8. m.span()
    返回一個二元組,內容分別是m.start(g)和m.end(g)的返回值
  9. m.re()
    產生這一匹配對象的正則表達式
  10. m.string()
    傳遞給match或者search用於匹配的字符串
  11. m.pos()
    搜索的起始位置。即字符串的開頭,或者start指定的位置(不常用)
  12. m.endpos()
    搜索的結束位置。即字符串的末尾位置,或者end指定的位置(不常用)

3.4 總結

  1. 對於正則表達式的匹配功能,Python沒有返回true和false的方法,但可以通過對match或者search方法的返回值是否是None來判斷
  2. 對於正則表達式的搜索功能,如果只搜索一次可以使用search或者match方法返回的匹配對象得到,對於搜索多次可以使用finditer方法返回的可迭代對象來迭代訪問
  3. 對於正則表達式的替換功能,可以使用正則表達式對象的sub或者subn方法來實現,也可以通過re模塊方法sub或者subn來實現,區別在於模塊的sub方法的替換文本可以使用一個函數來生成
  4. 對於正則表達式的分割功能,可以使用正則表達式對象的split方法,需要注意如果正則表達式對象有分組的話,分組捕獲的內容也會放到返回的列表中

3.5正則表達式的應用

字符驗證 只要是有規則的字符串,都可以利用正則表達式來驗證。下面給幾個常用的正則:

驗證email:

[0-9a-zA-Z]+@[0-9a-zA-Z]+\.com

解釋:[0-9a-zA-Z] 表示只能爲數字或字母,+ 表示一次或多次,@[0-9a-zA-Z]+.com是匹配@qq.com,@163.com這樣的情況。

驗證手機號碼:

1[3,5,7,8][0-9]{9}

解釋: 手機號一般都是以1開頭,第二位是3,5,7,8,後面9位數字 驗證網址:

^(?=^.{3,255}$)(https?://)?([w]{3}.)?([a-zA-Z0-9]+(.|/))+[a-zA-Z0-9]*

驗證網址的正則很多,因爲網址情況非常多,此正則能驗證如下形式的網址:
在這裏插入圖片描述

案例解讀

這裏只介紹比較用的

##1.re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回None;

p = re.compile('[0-9a-zA-Z]*\.[0-9a-zA-Z_-]*\.[a-z]*$')
x=p.match( '我愛中國,www.nveyun.com')

print(x)

None

#2.re.search 匹配整個字符串,這裏式郵箱,並返回找的結果
email=re.search('[0-9a-zA-Z]*\.[0-9a-zA-Z_-]*\.[a-z]*', '我愛中國,www.nveyun.com')
print(email.group())   

www.nveyun.com

###3.re.sub()   匹配到信息並執行替換, ‘|’或者
ste = re.sub('[,.。?::-_]|[0-9a-zA-Z]*\.[0-9a-zA-Z_-]*\.[a-z.]{0,10}', "",'我愛中國?www.nveyun.com.cn,')
print(ste)   

我愛中國

解讀上面的3的正則表達式
在這裏插入圖片描述

附錄:轉義符

轉義字符 描述
\(在行尾時) 續行符
\\ 反斜槓符號
\' 單引號
\" 雙引號
\a 響鈴
\b 退格(Backspace)
\e 轉義
\000
\n 換行
\v 縱向製表符
\t 橫向製表符
\r 回車
\f 換頁
\oyy 八進制數yy代表的字符,例如:\o12代表換行
\xyy 十進制數yy代表的字符,例如:\x0a代表換行
\other 其它的字符以普通格式輸出

附錄:常見正則表達式

正則表達式 代表的匹配字符
[0-9] 0123456789任意之一
[a-z] 小寫字母任意之一
[A-Z] 大寫字母任意之一
\d 等同於[0-9]
\D 等同於[^0-9]匹配非數字
\w 等同於[a-z0-9A-Z_]匹配大小寫字母、數字和下劃線
\W 等同於[^a-z0-9A-Z_]等同於上一條取非

答疑解惑Python羣:867300100

Python小白基礎視頻課 (點擊下面直通車)

Python小白基礎視頻課 (直通車

版權聲明:本文爲博主原創文章,歡迎交流分享,未經博主允許不得轉載。 https://blog.csdn.net/HHTNAN/article/details/84651583**

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章