英文中不少單詞中都有重疊出現(xiàn)的字母屈溉,比如shoot
或beep
,如果希望檢查某個單詞是否包含重疊出現(xiàn)的字母抬探,該怎么解決子巾?
匹配字母表達式是[a-z]
(這里暫不考慮大寫的情況)。但“重疊出現(xiàn)”的字母小压,取決于第一個[a-z]
運行時的匹配結(jié)果线梗,而不能預先設(shè)定。也就是說必須“知道”之前匹配的確切內(nèi)容:如果前面匹配的是e怠益,則后面只能是e仪搔;如果前面匹配的是a,后面就只能匹配a蜻牢。
上一節(jié)講到了引用分組烤咧,能引用某個分組內(nèi)的子表達式匹配的文本,但是引用都是在匹配完成后進行的抢呆,能不能在正則表達式中引用呢煮嫌?
答案是可以的,這種功能叫做反向引用(back-reference)抱虐,它允許在正則表達式內(nèi)部引用之前(左側(cè))的捕獲分組匹配的文本昌阿,其形式也是\num
,其中num
表示所引用分組的編號,編號規(guī)則與之前介紹的相同宝泵。
根據(jù)反向引用,查找連續(xù)重疊字母的表達式就是([a-z])\1
轩娶,其中的[a-z]
匹配第一個字母儿奶,再用括號將匹配分組,然后用\1
來反向引用鳄抒。
例3-24 用反向引用匹配重復字母
print(re.search(r'([a-z])\1', 'aabb')) # 'aa'
print(re.search(r'([a-z])\1', 'cc')) # 'cc'
print(re.search(r'([a-z])\1', 'mn')) # None
在日常開發(fā)中闯捎,我們經(jīng)常需要反向引用來建立前后聯(lián)系。最常見的就是解析html tag许溅。在html語法中瓤鼻,tag
包括open tag
和close tag
,它們經(jīng)常是成對出現(xiàn)的贤重,比如<bold>馬小跳</bold>
茬祷、<h1>title</h1>
。
有了反向引用并蝗,就可以先匹配open tag
祭犯,再匹配其他內(nèi)容,直到最近的close tag
為止:用([^>]+)
匹配open tag
的tag name
滚停,在匹配close tag
時沃粗,用\1
引用之前匹配的tag name
。
例3-25 用反向引用匹配成對的tag
pairedTagRegex = re.compile(r'<([a-zA-Z0-9]+)(\s*[^>]+)?>[\s\S]*?</\1>')
print(pairedTagRegex.search('<bold name="">馬小跳</bold>')) # <bold name="">馬小跳</bold>
print(pairedTagRegex.search('<h1 src="mxt">馬小跳</h1>')) # <h1 src="mxt">馬小跳</h1>
print(pairedTagRegex.search('<h1><span>馬小跳</span></h1>')) # <span>馬小跳</span>
反向引用還可以用在其他很多地方键畴,比如處理中文文本時最盅,查找“浩浩蕩蕩”、“明明白白”之類aabb
或者“如火如荼”起惕、“越來越好”這類abab
的四字詞語涡贱。
關(guān)于反向引用,還有一點需要強調(diào):反向引用重復的是對應(yīng)捕獲分組匹配的文本惹想,而不是之前的表達式盼产;也就是說,反向引用的是由之前表達式?jīng)Q定的具體文本勺馆,而不是符合某種規(guī)則的未知文本戏售。