正則表達式的深入學習

後向引用:

默認情況下,每個分組會自動擁有一個組號,規則是:從左向右,以分組的左括號爲標誌,第一個出現的分組的組號爲1,第二個爲2,以此類推。

後向引用用於重複搜索前面某個分組匹配的文本。例如,\1代表分組1匹配的文本

# 匹配字符串中連續出現的兩個相同的單詞
>>> a = '111'
>>> re.search('(.)\\1\\1',a)
<_sre.SRE_Match object; span=(0, 3), match='111'>

#同樣也可以用原生字符串來匹配
>>> re.search(r'(.)\1\1',a)
<_sre.SRE_Match object; span=(0, 3), match='111'>

`

自定義名稱的後向引用

s = 'hello blue go go hello'
p = re.compile(r'\b(?P<t_test>\w+)\b\s+(?P=t_test)\b')
print(re.findall(p,s))

貪婪與懶惰:

匹配的時候又分爲兩種模式 叫做貪婪模式/非貪婪模式,其中非貪婪模式又叫做懶惰模式

>>> re.search('<div>(.*)</div>',a)
<_sre.SRE_Match object; span=(0, 23), match='<div>aaa</div>bbb</div>'>

>>> re.search('<div>(.*?)</div>',a)
<_sre.SRE_Match object; span=(0, 14), match='<div>aaa</div>'>
>>> re.search('<div>(.*)</div>',a)  #這時候先匹配到</div>的時候會繼續往後匹配 如果還有</div>的話 那就繼續匹配 通通都要

>>> re.search('<div>(.*?)</div>',a) #這個就與上面的相反 如果匹配到了</div> 那麼就直接結束匹配

環視(斷言/零寬斷言):

環視,在不同的地方又稱之爲零寬斷言,簡稱斷言。
用一句通俗的話解釋:
環視,就是先從全局環顧一遍正則,(然後斷定結果,)再做進一步匹配處理。
斷言,就是先從全局環顧一遍正則,然後斷定結果,再做進一步匹配處理。

兩個雖然字面不一樣,意思卻是同一個,都是做全局觀望,再做進一步處理。

環視的作用相當於對其所在位置加了一個附加條件,只有滿足這個條件,環視子表達式才能匹配成功

環視主要有以下4個用法:

(?<=exp) 匹配前面是exp的數據
(?<!exp) 匹配前面不是exp的數據
(?=exp) 匹配後面是exp的數據
(?!exp) 匹配後面不是exp的數據

示例:

用python的re模塊給大家做試驗了哈

(?<=B)AAA 匹配前面是B的數據,即BAAA匹配,而CAAA不匹配
在這裏插入圖片描述
(?<!B)AAA 匹配前面不是B的數據,即CAAA匹配,而BAAA不匹配
在這裏插入圖片描述
AAA(?=B) 匹配後面是B的數據,即AAAB匹配,而AAAC不匹配
在這裏插入圖片描述
AAA(?!B) 匹配後面不是B的數據,即AAAC能匹配,而AAAB不能匹配
在這裏插入圖片描述

另外,還會看到(?!B)[A-Z]這種寫法,其實它是[A-Z]範圍裏,排除B的意思,前置的(?!B)只是對後面數據的一個限定,從而達到過濾匹配的效果。
在這裏插入圖片描述

例子: 需求:字母、數字組合,不區分大小寫,不能純數字或者純字母,6-16個字符。

通用正則:^[a-z0-9]{6,16}$ 字母數字組合,6-16個字符
排除純字母:(?!^[a-z]+$)
排除純數字:(?!^[0-9]+$)
組合起來:(?!^[a-z]+$)(?!^[0-9]+$)^[a-z0-9]{6,16}$

re.search('(?!^[a-z]+$)(?!^[0-9]+$)^[a-z0-9]{6,16}','qq1352483315')

注意,環視部分是不佔寬度的,所以有零寬斷言的叫法。
所謂不佔寬度,可以分成兩部分理解:
1、環視的匹配結果不納入數據結果
2、環視它匹配過的地方,下次還能用它繼續匹配。

第一點如何理解呢?我講下我自己的理解

簡單的來說 就是環視匹配的表達式匹配到的數據在整個正則表達式中匹配的數據中是不存在的。

比如:

>>> a = 'ABBB'
>>> re.search('(?<=A)BBB',a)
<_sre.SRE_Match object; span=(1, 4), match='BBB'>
>>>
>>> a = 'ABBB'
>>> re.search('[A]BBB',a)
<_sre.SRE_Match object; span=(0, 4), match='ABBB'>

正常的正則匹配能夠匹配到ABBB,但是在環視中 我們在ABBB 中匹配到的卻是BBB 不包含本身A 這就是第一個要點的解釋!

第二點的解釋:re.search('(?!^[a-z]+$)(?!^[0-9]+$)^[a-z0-9]{6,16}','qq1352483315')
大家可以看下這條表達式 我們通過這條表達式 來獲取了
1、不可以全是數字
2、不可以全是字母
3、必須是數字和字母混合 並且長度爲{6,16}
前面的(?!^[a-z]+$) (?!^[0-9]+$) 這兩條環視的表達式 是先環視一遍 然後纔開始後面的匹配 所以說環視的時候是還可以繼續匹配 一個例子簡單的說明:我們一共要跑400米 你跑了100米來拿東西 拿完東西然後又回到起點 才真正的開始計時自己的400米所要跑的時間

一個拓展部分:

擴展部分:
`[A-Z](?<=B)`   [A-Z]範圍等於B
`[A-Z](?<!B)`   [A-Z]範圍排除B
`(?!B)[A-Z]`    [A-Z]範圍排除B

平衡組:

看不懂,等自己需要的時候再去學~

模式修飾符:

模式修飾符在許多程序語言中都支持的,比如最常見的是i,不區分大小寫,如javascript裏的/[a-z0-9]/i,表示匹配字母數字,不區分大小寫。

又或者是python中的正則表達式中的re.I又或者是re.S 其實意思都是相通的 re.I對大小寫不敏感和re.S支持.來匹配換行

舉個例子:

a = 'abc'
re.search('(?i)[A-Z]+c')
結果:
<_sre.SRE_Match object; span=(0, 3), match='abc'>

又或者是

>>> re.search('[A-Z]+',a,re.I)
結果:
<_sre.SRE_Match object; span=(0, 3), match='abc'>

這個也就是可以說明對大小寫不敏感了

其他的模式修飾符 大家還可以自行學習

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