python3 正則匹配[^abc]和(?!abc)的區別(把多個字符作為一個整體匹配排除)


目的:把數字后面不為abc的字符串找出來

如1ab符合要求,2abc不符合要求

 1 str = '1ab'
 2 out = re.match(r'\d+(?!abc)',str)
 3 
 4 str1 = '1abc'
 5 out1 = re.match(r'\d+(?!abc)',str1)
 6 
 7 print('out:',out)
 8 print('out1:',out1)
 9 #
10 #out: <_sre.SRE_Match object; span=(0, 1), match='1'>
11 #out1: None
12 #

如果把(?!abc)改為[^abc],效果如下:

 1 str = '1ab'
 2 out3 = re.match(r'\d+[^abc]',str)
 3 
 4 str1 = '1abc'
 5 out4 = re.match(r'\d+[^abc]',str1)
 6 
 7 print('out:',out3)
 8 print('out1:',out4)
 9 
10 #
11 #out3: None
12 #out4: None

 總結:

(?!abc)是把abc當做一個整體進行匹配,字符串中不存在abc才能成功,abc作為一個整體進行匹配

[^abc]只要字符串中存在a/b/c中的任一個即匹配不成功,字符串中不能出現a/b/c中的任一個

 

------------------------------------------------------------------

更新:

之前沒有注意到(?!abc)方式匹配字符串不消耗字符串內容這句話,導致如果字符串中間排除一個子字符串時會出現錯誤。

更新關於這部分的理解

 

(?=...)  # 匹配字符串,且緊挨着匹配的字符串之后的字符等於...,才算匹配成功,且不消耗字符串內容

(?!...)  # 匹配字符串,且緊挨着匹配的字符串之后的字符不等於...,才算匹配成功,且不消耗字符串內容

(?<=...) # 匹配字符串,且緊挨着匹配的字符串之前的字符等於...,才算匹配成功,且不消耗字符串內容

(?<!...) # 匹配字符串,且緊挨着匹配的字符串之前的字符不等於...,才算匹配成功,且不消耗字符串內容

 

具體理解:

(?=...)為例

1 reg = re.compile('A(?=BC)')
2 reg.search('ABC')
3 reg.search('ABCDE')
4  
5  
6 # 輸出:
7 # <_sre.SRE_Match object; span=(0, 1), match='A'>
8 # <_sre.SRE_Match object; span=(0, 1), match='A'>
1 reg_1 = re.compile('A(?=BC)D')
2 print(reg_1.search('ABCD'))
3 
4 
5 # 輸出
6 # None

  reg = re.compile('A(?=BC)')

     reg.search('ABC')

  在這種情況下,匹配一個字符,這個字符包含'A',且'A'后面的字符為'BC',字符串'ABCD'符合規律

 但是,

reg_1 = re.compile('A(?=BC)D')
reg_1.search('ABCD')

就會出現問題,因為(?=...)括號內的表達式不消耗字符,也就是說匹配完字符串中的'A'之后,會判斷A之后的字符是否是'BC',匹配成功后正則表達式會繼續匹配字符串中'A'之后的字符是否是'D'
但是,在字符串中'A'之后是'B'就會出現匹配失敗,返回None.
https://blog.csdn.net/lxcnn/article/details/4304651 在這個鏈接中,解釋比較清楚.
在正則匹配過程中,各個子表達式會依次取得控制權,對字符串進行匹配.
比如例子中的
reg_1 = re.compile('A(?=BC)D')
1.'A(?=BC)D' 中,表達式'A'首先取得控制權,從字符串'ABCD'的開始位置('A'之前)進行匹配;
  匹配成功,控制權交給下一個正則子表達式(?=BC),匹配位置移動到字符串'ABCD'中的'A'之后('B'之前)
2.正則子表達式(?=BC)取得控制權,對當前匹配位置的右側字符進行匹配,判斷是否等於(?=BC)中的'BC'(即'A'后的'BC');
  匹配成功,控制權交給下一個正則子表達式'D',但是,因為(?=...)表達式不消耗字符,也就是說這個表達式是零寬度的,因此匹配位置不會往后移動.匹配位置依然在'A'之后.
3.正則子表達式'D'取得控制權,對當前位置('A'之后'B'之前)的右側字符進行匹配,判斷'A'之后的字符是否等於'D'.
  字符串'ABCD'中,'A'之后為'B',匹配失敗
4.進行下一輪匹配,又回到表達式'A'取得控制權,開始匹配位置不再是字符串首位置,此時從字符串'ABCD'中的'A'之后'B'之前的位置開始匹配,重復1~3步驟,不斷移動匹配位置進匹配

整個正則表達式匹配過程明了了.

不消耗字符串的意思就是這個子表達式為零寬度的,在匹配結束后不會向后移動匹配位置
 
        
 


 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM