770
京東網上商城
《正則表達式經典實例(第2版)》——2.12 把正則表達式的一部分重複多次
本節書摘來自異步社區《正則表達式經典實例(第2版)》一書中的第2章,第2.12節,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看
2.12 把正則表達式的一部分重複多次
問題描述
創建正則表達式來匹配下列種類的數字。
一個googol(一個100位的十進製整數)。
一個32位的十六進製整數。
一個32位的十六進製整數,帶有一個可選的h後綴。
-
一個浮點數,包含可選的整數部分、必需的小數部分和可選的指數部分。每個部分都允許任意多個數字。
解決方案
Googol\b\d{100}\b 正則選項:無 正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
十六進製整數
```javascript
\b[a-f0-9]{1,8}\b
正則選項:不區分大小寫
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
帶可選後綴的十六進製整數
\b[a-f0-9]{1,8}h?\b
正則選項:不區分大小寫
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
浮點數
\d*\.\d+(e\d+)?
正則選項:不區分大小寫
正則流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
討論
固定次數重複
量詞‹{n}›用來重複之前的正則表達式記號n次,其中n是一個正整數。在‹\b\d{100}\b›中的‹\d{100}›會匹配一個包含100個數字的字符串。你也可以通過把‹\d›敲100遍來達到同樣的效果。
‹{1}›重複之前的記號一次,這樣和沒有任何量詞是等價的。‹ab{1}c›與‹abc›是相同的正則表達式。
‹{0}›重複之前的記號0次,實際上也就是把它從正則表達式中刪除。‹ab{0}c›與‹ac›是相同的正則表達式。
可變次數重複
對於可變次數重複,我們使用量詞‹{n,m}›,其中n是一個正整數,並且m大於n。‹\b[a-f0-9]{1,8}\b›匹配一個包含1~8個數字的十六進製整數。對於可變次數重複,嚐試重複的順序就變得至關重要。這會在實例2.13中詳細講解。
如果n和m是相等的,那麼我們就會得到固定次數的重複。‹\b\d{100,100}\b›與‹\b\d{100}\b›是相同的正則表達式。
無限次數重複
量詞‹{n,}›支持無限次數重複,其中n是一個正整數。實際上,無限次數重複是一個沒有上限的可變次數重複。
‹\d{1,}›匹配至少一個數字,‹\d+›也一樣。在一個不是量詞的正則表達式記號之後添加一個加號,意味著“一次或多次”。實例2.13會講解在量詞之後跟加號的含義。
‹\d{0,}›匹配至少0個數字,‹\d*›也一樣。星號永遠都意味著“0次或多次”。除了支持無限次數重複之外,‹{0,}›和星號還把之前的記號變成了可選的。
設置可選內容
如果我們使用可變次數重複,並把n設置為0,事實上我們就是把在該量詞之前的記號變成了可選的。‹h{0,1}›匹配一次‹h›或者根本不存在。如果不存在h,那麼‹h{0,1}›會得到一個長度為0的匹配。如果你使用‹h{0,1}›來作為一個正則表達式,那麼它會在目標文本中每個不是h的字符之前找到一個長度為0的匹配。每個h則會成功匹配一個字符(也就是h)。
‹h?›與‹h(0,1)›的效果是一樣的。在一個合法和完整的非量詞正則表達式記號之後的問號意味著“0或1次”。下一個實例會解釋在量詞之後的問號的含義。
在一個起始括號之後使用問號或者任意其他量詞,都是一個語法錯誤。Perl和沿用它的流派利用它為正則語法添加“Perl擴展”。前麵的實例講解了非捕獲分組和命名捕獲分組,它們都使用了在起始括號之後的問號來作為其語法的一部分。這些問號根本不是量詞,它們隻是屬於非捕獲分組和命名捕獲分組的語法中的一部分。隨後的實例中會講解使用‹(?›語法的更多不同用途的分組。
重複分組
如果在分組的結束括號之後放一個量詞的話,那麼整個分組就會重複。‹(?:abc){3}›與‹abcabcabc›是相同的。
量詞還可以進行嵌套。‹(e\d+)?›匹配一個e之後跟著至少一個數字,或者是一個長度為0的匹配。在我們的浮點數的正則表達式中,這是可選的指數部分。
捕獲分組也可以重複。在實例2.9中解釋過,分組匹配在每次引擎退出該分組的時候捕獲文本,並會覆蓋該分組在之前匹配的任何文本。‹(\d\d){1,3}›會匹配一個包含2個、4個或6個數字的字符串。引擎會退出該分組3次。當這個正則表達式匹配到123456的時候,捕獲分組中保存的是56,因為該分組的最後一次重複存儲的是56。另外兩次分組匹配的文本,也就是12和34,是無法獲取的。
‹(\d\d){3}›會與‹\d\d\d\d(\d\d)›捕獲相同的文本。如果想要用捕獲分組來捕獲所有2個、4個或6個字符,而不隻是最後2個,就必須用捕獲分組包圍量詞,而不隻是重複該捕獲分組:‹((?:\d\d){1,3})›。這裏我們用非捕獲分組取代了捕獲分組的分組功能。我們也可以使用兩個捕獲分組:‹((\d\d){1,3})›。在後一個正則表達式匹配123456的時候,‹\1›中保存的是123456,而在‹\2›中則保存了56。
隻有.NET的正則表達式引擎才支持獲取捕獲分組的所有重複捕獲的文本。如果直接查找該分組的Value屬性,你會得到字符串56,就像所有其他正則表達式引擎一樣。在正則表達式中的反向引用和替代文本也會代入56,但是如果使用分組的CaptureCollection,你就會得到一個棧,其中包含56、34和12。
最後更新:2017-06-06 07:35:33