目前為止,總共介紹了括號(hào)的三種用途:
- 分組:將相關(guān)的元素歸攏到一起,構(gòu)成單個(gè)元素;
- 多選結(jié)構(gòu):規(guī)定可能出現(xiàn)的多個(gè)子表達(dá)式;
- 引用分組:將子表達(dá)式匹配的文本存儲(chǔ)起來,供之后引用
這三種用途并不是彼此獨(dú)立的,而是相互重疊的:
- 單純的分組可以視為“只包含一個(gè)多選分支的多選結(jié)構(gòu)”;
- 整個(gè)多選結(jié)構(gòu)也會(huì)被視為單個(gè)元素,可以由一個(gè)量詞限定;
- 只要出現(xiàn)了括號(hào),正則表達(dá)式在匹配時(shí)就會(huì)把括號(hào)內(nèi)的子表達(dá)式存儲(chǔ)起來提供引用;
但有時(shí)如果不需要引用,保存括號(hào)分組的引用信息就會(huì)影響性能;如果表達(dá)式比較復(fù)雜,要處理的文本又很多,更可能嚴(yán)重影響性能。
為了解決這種問題,正則表達(dá)式提供了非捕獲分組(non-capturing group)。非捕獲分組類似普通捕獲分組,只是在開括號(hào)后面緊跟一個(gè)問號(hào)和冒號(hào)(?:...),這樣的括號(hào)叫做非捕獲型括號(hào),它只能限定量詞的作用范圍,不能捕獲文本。在引用分組時(shí),分組的編號(hào)同樣會(huì)按開括號(hào)出現(xiàn)的順序從左向右遞增,只是必須以捕獲分組為準(zhǔn),非捕獲分組會(huì)略過。
例3-35 非捕獲型分組的使用
# 非捕獲型分組
print(re.search(r'(\d{4})-(\d{2})-(\d{2})', '2018-12-20').group(1)) # 2018
print(re.search(r'(?:\d{4})-(\d{2})-(\d{2})', '2018-12-20').group(1)) # 12
非捕獲型分組不需要保存匹配的文本,整個(gè)表達(dá)式的效率也因此提高,但是看起來不如捕獲分組美觀。不過,如果只需要使用括號(hào)的分組或者讀選結(jié)構(gòu)的功能,而沒有用到引用分組,則應(yīng)當(dāng)盡量使用非捕獲型括號(hào)。