【原創】如何治療使用python中re模塊group、groups與findall分組匹配后產生的“眩暈反應”


 
 
直接先上例子
>>> re.search('(book+)', 'mebookbookme').groups()
('book',)
>>> re.search('(book+)', 'mebookbookme').group()
'book'
>>> re.search('(book)+', 'mebookbookme').groups()
('book',)
>>> re.search('(book)+', 'mebookbookme').group()
'bookbook'
>>> re.findall('(book)+', 'mebookbookme')
['book']
>>> re.findall('(book+)', 'mebookbookme')
['book', 'book']
 
是不是被整暈了?
 
這時,你需要來點理論💊回下血:
1. 首先要明白:
        search、match與findall在對正則表達式上匹配次數的區別:
         search和match(從頭開始匹配)都是只匹配字符串中第一次滿足正則表達式pattern的內容
        findall則是直接把字符串中所有滿足正則表達式pattern的內容匹配出來
2. 其次要弄明白:
        (1)group和groups是兩個不同的函數,他們都是搭配search和match后的匹配對象來使用的,因此只會匹配出字符串中第一次滿足正則表達式pattern的內容。
        (2)之所以用group和groups是因為在正則表達式中我們會用到括號()來進行單元分組,進行重復內容匹配(小括號后用+號)或指定內容展示(用group(組號)或groups())的操作。
        (3)group和groups的用法區別如下:
 
【m.group()】(這里m是search或者match后生成的對象)
        m.group()可以括號內不填內容,也可以傳入一個數字N,即m.group(N)。以下分情況說明:
 
        <不傳入N或傳入N=0>
m.group() == m.group(0) == 展示匹配到的第一次滿足正則表達式pattern的全部內容(所有匹配的字符)
  這里直接展示匹配到的全部內容,所以展示的就 與括號無關了,這個是API規定的,例如'(book)+'的正則表達式可以對'yourbookbook'匹配展示出'bookbook'。
 
        <傳入N>0>
        返回第N組括號匹配的字符。(正則表達式內有幾個()就有幾個分組)
        m.group(1)、m.group(2)、... 的方式都只會展示()匹配到的對應分組編號括號里的內容,例如'(book)+'的正則表達式用m.group(1)對'yourbookbook'匹配也只會展示一個'book'(因為只有1組小括號,就只有1個分組)。
 
【m.groups()】
        m.groups() 返回所有括號匹配的字符(正則表達式中有幾個括號就會有幾個分組的字符串內容展示),以tuple格式作為容器返回。
m.groups() == (m.group(1), m.group(2), ...)
 

什么,還看不懂?
看來💊不能停,逐個分析吧:
  1. 首先,分析下正則表達式book+和(book+)
        search對於'mebookbookme'字符串,用book+或者(book+)這樣的正則表達式匹配到全部內容本來就是'book'
        (因為這里+號是僅對k這個字母來匹配重復的,別搞混了)
>>> re.search('book+', 'mebookbookme')
<_sre.SRE_Match object; span=(2, 6), match='book'>
>>> re.search('(book+)', 'mebookbookme')
<_sre.SRE_Match object; span=(2, 6), match='book'>
            所以不管groups()還是group(),都是'book'(一個book)
 
  1. 而search對於(book)+匹配到的全部內容是'bookbook'
>>> re.search('(book)+', 'mebookbookme')
<_sre.SRE_Match object; span=(2, 10), match='bookbook'>
        使用group()是把正則匹配到的內容都展示,即返回'bookbook'
        
>>> re.search('(book)+', 'mebookbookme').group()
'bookbook'
   使用group(1)是把第一個(當然這里正則只有一個)小括號里匹配的內容展示,即返回'book'
  使用groups()是把所有小括里匹配的內容以元組打包了返回(當然這里只有一個小括號),即返回('book',)
        
>>> re.search('(book)+', 'mebookbookme').groups()
('book',)

 

     3. 使用findall中匹配分組小括號()后帶+的例子,和group(1)、groups()展示的類似
        就是正則表達式里()后+號匹配到的重復內容是不會展示的,只會展示小括號內的一次內容,說白了就是正則表達式里有幾個小括號()就展示幾個括號()內的匹配內容。當然這里正則表達式里只有一個小括號(),所以findall返回列表的每個元素就是一個字符串'book'
        
>>> re.findall('(book)+', 'mebookbookme')
['book']
>>> re.findall('(book+)', 'mebookbookme')
['book', 'book']

    ★第一個findall對(book)+的展示,直接把+號重復的分組合並為一個單元來展示(這個跟search的groups對於(book)+的展示是一樣的)

    ★第二個findall對(book+)的展示,則是把所有分組都展示出來

  再加點💊,補充一個例子來說明一下findall:
 
         下面的例子不管字符串中'ab'和'c'重復幾次,都只會展示一個'ab'和一個'c',當然之所以返回了兩個元組,是因為findall
>>> re.findall('(ab)+(c)+', 'abcc123ababcccc')
[('ab', 'c'), ('ab', 'c')]

 


 

如果我們是要對'mebookbookme'匹配出'bookbook',怎么做呢?
 
1. 首先分析的是用match、search還是findall?
        'mebookbookme'中'bookbook'不是出現在第一個字母開始的,所以不能用match;
        'bookbook'模式只出現了一次(當然也就是第一次出現'bookbook'模式),因此可以用search匹配到;
        當然findall能匹配到所有出現的'bookbook'模式,是肯定能用的。
 
2. 具體分析:
(1)使用search
        使用'(book)+'的方式來search,匹配到的完整內容就是'bookbook',選用group()或group(0)返回完整內容就可以了。
 
>>> re.search('(book)+', 'mebookbookme').group()
'bookbook'
>>> re.search('(book)+', 'mebookbookme').group(0)
'bookbook'

 

        如果要使用group(1)或groups()[0]呢,該用什么正則表達式?
        可以使用'((?:book)+)'的非捕獲組(非編號組)的方式,即(?:表達式)的形式,這個小括號是沒有進入分組編號的。外頭之所以還要加個小括號,就是因為我們一旦用了group(1)或groups()[0]這樣的方式,必須要有編號為1的小括號分組。
        (PS:當然這個例子這樣做太麻煩,肯定不會選用這種方式,只是為了說明用法)
 
>>> re.search('((?:book)+)', 'mebookbookme').group(1)
'bookbook'
>>> re.search('((?:book)+)', 'mebookbookme').groups()[0]
'bookbook'

 

(2)使用findall
        使用findall如果搭配小括號分組的話由於同樣會只返回小括號里的內容,所以不能用'(book)+'的正則表達式,但可以采用非捕獲組(非編號組)的方式。
 
>>> re.findall('(?:book)+', 'mebookbookme')
['bookbook']
>>> re.findall('(?:book)+', 'mebookbookme')[0]
'bookbook'

 

 轉載請注明出處:https://www.cnblogs.com/oceanicstar/p/9244783.html


免責聲明!

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



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