重複

正則表達式第一件能作的事是可以匹配不定長的字符集,而這是其它能做用在字符串上的方法所不能作到的。 不過,若是那是正則表達式惟一的附加功能的話,那麼它們也就不那麼優秀了。它們的另外一個功能就是你能夠指定正則表達式的一部分的重複次數。正則表達式

咱們討論的第一個重複功能的元字符是  並不匹配字母字符 "*";相反,它指定前一個字符能夠被匹配零次或更屢次,而不是隻有一次。homebrew

舉個例子,ca*t 將匹配 "ct" (0 個 "a" 字符), "cat" (1 個 "a"), "caaat" (3 個 "a" 字符)等等。RE 引擎有各類來自 C 的整數類型大小的內部限制,以防止它匹配超過20億個 "a" 字符;你也許沒有足夠的內存去建造那麼大的字符串,因此將不會累計到那個限制。內存

象 * 這樣地重複是「貪婪的」;當重複一個 RE 時,匹配引擎會試着重複儘量多的次數。若是模式的後面部分沒有被匹配,匹配引擎將退回並再次嘗試更小的重複。字符串

一步步的示例可使它更加清晰。讓咱們考慮表達式 a[bcd]*b。它匹配字母 "a",零個或更多個來自類 [bcd]中的字母,最後以 "b" 結尾。如今想想該 RE 對字符串 "abcbd" 的匹配。io

Step Matched Explanation
1 a a 匹配模式
2 abcbd 引擎匹配 [bcd]*,並盡其所能匹配到字符串的結尾
3 Failure 引擎嘗試匹配 b,但當前位置已是字符的最後了,因此失敗
4 abcb 退回,[bcd]*嘗試少匹配一個字符。
5 Failure 再次嘗次b,但在當前最後一位字符是"d"。
6 abc 再次退回,[bcd]*只匹配 "bc"。
7 abcb 再次嘗試 b ,此次當前位上的字符正好是 "b"

RE 的結尾部分如今能夠到達了,它匹配 "abcb"。這證實了匹配引擎一開始會盡其所能進行匹配,若是沒有匹配而後就逐步退回並反覆嘗試 RE 剩下來的部分。直到它退回嘗試匹配 [bcd] 到零次爲止,若是隨後仍是失敗,那麼引擎就會認爲該字符串根本沒法匹配 RE 。table

另外一個重複元字符是 +,表示匹配一或更屢次。請注意 和 + 之間的不一樣; 匹配零或更屢次,因此能夠根本就不出現,而 + 則要求至少出現一次。用同一個例子,ca+t 就能夠匹配 "cat" (1 個 "a"), "caaat" (3 個 "a"), 但不能匹配 "ct"。class

還有更多的限定符。問號 ? 匹配一次或零次;你能夠認爲它用於標識某事物是可選的。例如:home-?brew 匹配 "homebrew" 或 "home-brew"。方法

最複雜的重複限定符是 {m,n}(注意m,n之間不能有空格),其中 m 和 n 是十進制整數。該限定符的意思是至少有 m 個重複,至多到 n 個重複。舉個例子,a/{1,3}b 將匹配 "a/b","a//b" 和 "a///b"。它不能匹配 "ab" 由於沒有斜槓,也不能匹配 "a////b" ,由於有四個。tab

你能夠忽略 m 或 n;由於會爲缺失的值假設一個合理的值。忽略 m 會認爲下邊界是 0,而忽略 n 的結果將是上邊界爲無窮大 -- 其實是先前咱們提到的20億,但這也許同無窮大同樣。di

+

 

細心的讀者也許注意到其餘三個限定符均可以用這樣方式來表示。 {0,} 等同於 ,{1,} 等同於 +,而{0,1}則與 ? 相同。若是能夠的話,最好使用 ,+,或?。很簡單由於它們更短也更容易懂。

相關文章
相關標籤/搜索