閱讀924 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《正則表達式經典實例(第2版)》——2.10 再次匹配先前匹配的文本

本節書摘來自異步社區《正則表達式經典實例(第2版)》一書中的第2章,第2.10節,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.10 再次匹配先前匹配的文本

問題描述
創建一個正則表達式來匹配按照yyyy-mm-dd格式的“神奇”日期。神奇日期指的是年份後2位與月份和該月的日期都是相同的數字。例如,2008-08-08就是一個神奇日期。你可以假設目標文本中的所有日期都是有效的。這個正則表達式並不需要考慮去掉像9999-99-99這樣的日期,因為它們不會出現在目標文本中。你隻需要找到神奇的日期即可。

解決方案

\b\d\d(\d\d)-\1-\1\b
正則選項:無
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby

討論
為了在正則表達式中匹配先前匹配到的文本,我們首先必須記錄上次匹配的文本。這可以使用捕獲分組來實現,實例2.9中已經講解過。在此之後,我們可以使用反向引用(backreference)來在該正則表達式中的任何地方匹配相同的文本。你可以使用一個反斜杠之後跟一個單個數字(1~9)來引用前9個捕獲分組。而第10~99組,則要使用‹\10›~‹\99›。

screenshot不要使用\01。它或者是一個八進製的轉義,或者會產生一個錯誤。在本書中我們不會用到八進製轉義,因為\xFF這樣的十六進製轉義更加容易理解。
當正則表達式‹\b\d\d(\d\d)-\1-\1\b›遇到2008-08-08的時候,開始的‹\d\d›會匹配20。接著正則引擎會進入捕獲分組,並記錄目標文本中所在的位置。

在捕獲分組中的‹\d\d›會匹配08,然後引擎會到達分組的右括號。在這個點上,匹配的部分08會被保存到1號捕獲分組中。

下一個記號是連字符,它會按照字麵進行匹配。接著就遇到了反向引用。正則引擎會檢查第一個捕獲分組的內容:08。然後引擎會試圖按照字麵來匹配這個文本。如果該正則表達式是不區分大小寫的,那麼捕獲分組也會按照這種方式進行匹配。在這裏,反向引用匹配成功。下一個連字符和反向引用也會匹配成功。最終,單詞分界符會匹配目標文本的結尾,這樣就找到了一個完整匹配:2008-08-08。現在捕獲分組中依然保存的是08。

如果一個捕獲分組被重複,這可以通過量詞(實例2.12)或者是回溯(實例2.13)來實現,每次捕獲分組匹配成功,都會覆蓋之前保存的捕獲分組匹配的內容。對該分組的反向引用隻會匹配該分組最後一次捕獲到的文本。

如果同一個正則表達式遇到2008-05-24 2007-07-07的時候,當‹\b\d\d(\d\d)›匹配到2008的時候,該分組第一次捕獲到的內容08,會被保存到第一個(也是唯一一個)捕獲分組中。接下來,連字符會匹配它自身。反向引用在試圖用05來匹配‹08›的時候,匹配失敗。

由於在該正則表達式中不存在其他的選擇分支,引擎會放棄匹配嚐試。這包括清除所有的捕獲分組。當引擎再次嚐試的時候,從目標文本中的第一個0開始,‹\1›不再存有任何文本內容。

接下來繼續處理2008-05-24 2007-07-07,該分組下一次會捕獲到內容是當‹\b\d\d(\d\d)›匹配到2007的時候,它會把07保存起來。接下來,連字符匹配自身。現在反向引用會試圖匹配‹07›。這次匹配是成功的,接著下一個連字符、反向引用以及單詞邊界都匹配成功。結果是找到了2007-07-07。

因為正則引擎是從前向後處理的,因此應當把捕獲括號放到反向引用的前麵。正則表達式‹\b\d\d\1-(\d\d)-\1›和‹\b\d\d\1-\1-(\d\d)\b›永遠不可能匹配到任何東西。因為這裏的反向引用是在捕獲分組之前出現的,而它還沒有捕獲到任何東西。除非你使用的是JavaScript,否則反向引用指向還沒有進行匹配嚐試的分組時,它總是會匹配失敗。

還沒有參與匹配的分組,並不等同於捕獲到長度為0的分組。對一個長度為0的捕獲分組的反向引用總是會匹配成功。當‹(^)\1›匹配字符串的開始的時候,第一個捕獲分組會捕獲到^號的長度為0的匹配,從而‹\1›會匹配成功。在實踐中,這會發生在當所有捕獲分組的內容都是可選的情況下。

screenshot JavaScript是我們所知道的唯一與正則表達式中幾十年反向引用的傳統相違背的流派。在JavaScript中,或者至少在遵循JavaScript標準的實現中,對一個還沒有參與匹配的分組的反向引用總是會匹配成功,這同捕獲了長度為0的匹配的分組的反向引用是一樣的。因此,在JavaScript中,‹\b\d\d\1-\1-(\d\d)\b›會成功匹配12--34。

最後更新:2017-06-06 07:35:28

  上一篇:go  為什麼要選擇CS專業,助力未來IT人的報考指南
  下一篇:go  阿裏雲免費套餐邀請碼免費發放 限阿裏雲幸運券用戶