我找到了這本關於正則表達式的出色教程 ,儘管我直觀地理解「貪婪」,「勉強」和「可能」量詞的做用,但個人理解彷佛還存在嚴重的漏洞。 正則表達式
具體來講,在如下示例中: 工具
Enter your regex: .*foo // greedy quantifier Enter input string to search: xfooxxxxxxfoo I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13. Enter your regex: .*?foo // reluctant quantifier Enter input string to search: xfooxxxxxxfoo I found the text "xfoo" starting at index 0 and ending at index 4. I found the text "xxxxxxfoo" starting at index 4 and ending at index 13. Enter your regex: .*+foo // possessive quantifier Enter input string to search: xfooxxxxxxfoo No match found.
解釋提到了吃掉整個輸入字符串,字母被消耗 ,匹配器退回 ,最右端出現的「 foo」已被檢討 ,等等。 測試
不幸的是,儘管有很好的比喻,我仍是不明白什麼是被誰吃掉......你知道另外一個教程,說明(簡潔) 如何正則表達式引擎的工做? spa
或者,若是有人能夠用不一樣的措辭解釋下一段,那將不勝感激: code
第一個示例使用貪婪量詞。*查找「任何」,零次或屢次,後跟字母「 f」,「 o」,「 o」。 因爲量詞是貪婪的,所以表達式的。*部分首先會吃掉整個輸入字符串。 此時,整個表達式沒法成功,由於最後三個字母(「 f」,「 o」,「 o」)已經被消耗( 由誰來使用? )。 所以,匹配器一次( 從右到左? )緩慢退回一個字母,直到最右邊的「 foo」出現反響( 這是什麼意思? ),這時匹配成功而且搜索結束。 教程
可是,第二個示例是不情願的,所以它從首先消耗( 由誰來? )「什麼都沒有」開始。 由於「 foo」沒有出如今字符串的開頭,因此它被迫吞下( 誰吞了?)第一個字母(「 x」),從而在0和4處觸發第一個匹配。咱們的測試工具繼續進行直到輸入字符串用盡。 它在4和13找到另外一個匹配項。 索引
第三個示例找不到匹配項,由於量詞是全部格。 在這種狀況下,整個輸入字符串將由。* +( 如何使用 )使用,而在表達式末尾不留任何內容來知足「 foo」。 對於但願在不退縮的狀況下抓住全部東西的狀況,請使用全部格量詞( backful意味着什麼? ); 若是沒有當即找到匹配項,它將賽過等效的貪婪量詞。 字符串
貪婪:「匹配最長的字符序列」 get
勉強:「匹配儘量短的字符序列」 input
擁有:這有點奇怪,由於它不會(與貪婪和不情願相反)嘗試爲整個正則表達式找到匹配項。
順便說一句:沒有任何正則表達式模式匹配器實現將使用回溯。 全部現實生活中的模式匹配器都很是快-幾乎與正則表達式的複雜性無關!
這是我使用單元格和索引位置的見解(請參見此處的圖,以區分單元格和索引)。
貪婪-儘量匹配貪婪量詞和整個正則表達式。 若是沒有匹配項,則在貪婪量詞上回溯。
輸入字符串: xfooxxxxxxfoo
正則表達式: 。* foo
上面的正則表達式包含兩個部分:
(我和
(ii)'foo'
下面的每一個步驟將分析這兩個部分。 大括號內說明了與「經過」或「失敗」匹配的其餘註釋。
第1步:
(i)。* = xfooxxxxxxfoo-經過('。*'是一個貪婪的量詞,將使用整個輸入字符串)
(ii)foo =索引13以後沒有字符可匹配-失敗
比賽失敗。
第2步:
(i)。* = xfooxxxxxxfo-經過(貪婪量詞'。*'的回溯)
(ii)foo = o-失敗
比賽失敗。
第三步:
(i)。* = xfooxxxxxxf-經過(貪婪量詞「。*」的回溯)
(ii)foo = oo-失敗
比賽失敗。
第四步:
(i)。* = xfooxxxxxx-經過(貪婪量詞「。*」的回溯)
(ii)foo = foo-經過
報告比賽
結果:1場比賽
我發現文本「 xfooxxxxxxfoo」從索引0開始到索引13結束。
勉強的-儘量少地匹配勉強的量詞,並匹配整個正則表達式。 若是不匹配,則將字符添加到勉強的量詞中。
輸入字符串: xfooxxxxxxfoo
正則表達式: 。*?foo
上面的正則表達式包含兩個部分:
(一世) '。*?' 和
(ii)'foo'
第1步:
。*? =''(空白)-經過(與儘量少的量詞'。*?'匹配。具備''的索引0是匹配項。)
foo = xfo-失敗(單元格0,1,2-即索引介於0和3之間)
比賽失敗。
第2步:
。*? = x-經過(將字符添加到勉強的量詞「。*?」。具備「 x」的單元格0是匹配項。)
foo = foo-經過
報告比賽
第三步:
。*? =''(空白)-經過(與儘量少的勉強量詞'。*?'匹配。具備''的索引4是匹配項。)
foo = xxx-失敗(單元格4,5,6-即索引介於4到7之間)
比賽失敗。
第四步:
。*? = x-經過(將字符添加到不但願的量詞「。*?」。單元格4。)
foo = xxx-失敗(單元格5,6,7-即索引介於5到8之間)
比賽失敗。
步驟5:
。*? = xx-經過(將字符添加到勉強的量詞'。*?'。單元格4到5。)
foo = xxx-失敗(單元格6,7,8-即索引在6到9之間)
比賽失敗。
步驟6:
。*? = xxx-經過(將字符添加到勉強的量詞'。*?'。單元格4到6。)
foo = xxx-失敗(單元格7,8,9-即索引介於7到10之間)
比賽失敗。
步驟7:
。*? = xxxx-經過(將字符添加到勉強的量詞「。*?」。單元格4至7。)
foo = xxf-失敗(單元格8,9,10-即8到11之間的索引)
比賽失敗。
步驟8:
。*? = xxxxx-經過(將字符添加到勉強的量詞'。*?'。單元格4到8。)
foo = xfo-失敗(單元格9,10,11-即9到12之間的索引)
比賽失敗。
步驟9:
。*? = xxxxxx-經過(將字符添加到勉強的量詞'。*?'。單元格4到9。)
foo = foo-經過(單元格十、十一、12-即介於10和13之間的索引)
報告比賽
步驟10:
。*? =''(空白)-經過(儘量少地匹配勉強的量詞'。*?'。索引13爲空白。)
foo =沒有字符能夠匹配-失敗(索引13以後沒有要匹配的字符)
比賽失敗。
結果:2場比賽
我發現文本「 xfoo」從索引0開始到索引4結束。
我發現文本「 xxxxxxfoo」從索引4開始到索引13結束。
擁有-儘量匹配全部格量詞並匹配整個正則表達式。 不要回溯。
輸入字符串: xfooxxxxxxfoo
正則表達式: 。* + foo
上面的正則表達式包含兩個部分:「。* +」和「 foo」。
第1步:
。* + = xfooxxxxxxfoo-經過(儘量匹配全部格量詞'。*')
foo =沒有字符能夠匹配-失敗(索引13以後沒有匹配項)
比賽失敗。
注意:不容許回溯。
結果: 0場比賽
貪婪量化涉及在迭代過程當中使用字符串的全部其他未驗證字符進行模式匹配。 未經驗證的字符從活動序列開始。 每次不進行匹配時,末尾的字符將被隔離,並再次執行檢查。
當活動序列僅知足正則表達式模式的前導條件時,將嘗試針對隔離區驗證其他條件。 若是此驗證成功,則隔離區中的匹配字符將獲得驗證,剩餘的不匹配字符將保持未驗證狀態,並將在下一次迭代中從新開始該過程時使用。
字符流是從活動序列進入隔離區的。 結果是,匹配中包含了儘量多的原始序列。
勉強量化與貪婪限定基本相同,不一樣之處在於字符流是相反的,也就是說,它們從隔離區開始並流入活動序列 。 結果是,匹配中包含的原始序列越少越好。
全部權量化沒有隔離區 ,包括固定激活序列中的全部內容 。
這只是個人練習輸出,能夠將場景可視化-
我會試一試。
貪婪的量詞首先會盡量匹配。 所以.*
匹配整個字符串。 而後,匹配器嘗試匹配如下的f
,但沒有剩餘字符。 所以它「回溯了」,使貪婪的量詞少匹配一件事(使字符串末尾的「 o」不匹配)。 那仍然與正則表達式中的f
不匹配,所以它又「回溯」了一步,使貪婪的量詞再次匹配少了一點(使字符串末尾的「 oo」不匹配)。 它仍然與正則表達式中的f
不匹配,所以它又回退了一步(使字符串末尾的「 foo」不匹配)。 如今,匹配器最終匹配正則表達式中的f
,而且o
和下一個o
也被匹配。 成功!
勉強或「非貪婪」的量詞首先匹配得儘量少。 所以, .*
首先不匹配任何內容,從而使整個字符串不匹配。 而後,匹配器嘗試匹配後跟的f
,可是字符串的不匹配部分以「 x」開頭,所以不起做用。 所以,匹配器回溯,使非貪婪量詞又匹配一件事(如今匹配「 x」,而使「 fooxxxxxxfoo」不匹配)。 而後,它嘗試匹配成功的f
,而且正則表達式中的o
和下一個o
也匹配。 成功!
在您的示例中,而後按照相同的過程,以字符串的剩餘不匹配部分從新開始該過程。
全部格量詞就像貪婪的量詞同樣,可是不會回溯。 所以,它以.*
開頭,匹配整個字符串,不留任何不匹配的內容。 這樣就沒有其餘要與正則表達式中的f
匹配的東西了。 因爲全部格量詞不會回溯,所以匹配失敗。