考慮匹配圓括號內字符串的問(wèn)題,允許無(wú)限嵌套括號。如果不使用遞歸,
最好的方式是使用一個(gè)模式匹配固定深度的嵌套。它不能處理任意深度的嵌套。 perl
5.6 提供了一個(gè)實(shí)驗性的功能允許正則表達式遞歸。
特殊項 (?R) 提供了遞歸的這種特殊用法。
這個(gè)PCRE模式解決了圓括號問(wèn)題(假設
PCRE_EXTENDED 選項被設置了,
因此空白字符被忽略):
\( ( (?>[^()]+) | (?R) )* \)
首先,它匹配一個(gè)左括號。 然后它匹配任意數量的非括號字符序列或一個(gè)模式自身的遞歸匹配(比如, 一個(gè)正確的括號子串),最終,匹配一個(gè)右括號。
這個(gè)例子模式包含無(wú)限重復的嵌套,因此使用了一次性子組匹配非括號字符,
這在模式應用到模式不匹配的字符串時(shí)非常重要。比如,
當它應用到
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
時(shí)就會(huì )很快的產(chǎn)生”不匹配”結果。
然而,如果不使用一次性子組,這個(gè)匹配將會(huì )運行很長(cháng)時(shí)間,
因為有很多途徑讓 + 和 * 重復限定分隔目標字符串,
并且在報告失敗之前需要測試所有路徑。
所有捕獲子組最終被設置的捕獲值都是從遞歸最外層子模式捕獲的值。
如果上面的模式匹配
(ab(cd)ef)
,捕獲子組最終被設置的值為 ”ef”,
即頂級得到的最后一個(gè)值。如果增加了額外的括號
\( ( ( (?>[^()]+) | (?R) )* ) \)
捕獲到的字符串就是頂層括號的匹配內容 ”ab(cd)ef”。
如果在模式中有超過(guò) 15 個(gè)捕獲括號,
PCRE 在遞歸期間就會(huì )使用 pcre_malloc 分配額外的內存來(lái)存儲數據,
隨后通過(guò) pcre_free 釋放他們。如果沒(méi)有內存可被分配,它就僅保存前 15 個(gè)捕獲括號,
在遞歸內部無(wú)法給出內存不夠用的錯誤。
(?1)
、(?2)
等可以用于遞歸子組。
這同樣可以用于命名子組:
(?P>name)
或 (?P&name)
。
如果遞歸子組語(yǔ)法在它提到的子組括號外部使用(無(wú)論是子組數字序號還是子組名稱(chēng)),
這個(gè)操作就相當于程序設計語(yǔ)言中的子程序。
前面一些有一個(gè)例子指出模式 (sens|respons)e and \1ibility
匹配 ”sense and
responsibility” 和 ”response and responsibility”,但是不匹配 ”sense and
responsibility”。如果用模式 (sens|respons)e and
(?1)ibility
替代,
它會(huì )像匹配那兩個(gè)字符串一樣匹配 ”sense and responsibility”。
這種引用方式意義是緊接著(zhù)匹配引用的子模式。(譯注:
后向引用只匹配引用的子組之前匹配的結果,
這里的遞歸語(yǔ)法引用是拿引用的子模式重新匹配。)
目標字符串的最大長(cháng)度是 int 型變量可以存儲的最大正整數。然而, PCRE 使用遞歸處理子組和無(wú)限重復。 這就是說(shuō)對于某些模式可用的??臻g可能會(huì )受目標字符串限制。