正則表達式量詞匹配方式的講解(上篇)

cover-20200712.png

若是想要系統的學習正則表達式的話,那麼關於量詞的匹配方式是必需要掌握好的內容。量詞的匹配方式有三種,分別是匹配優先忽略優先以及佔有優先。今天這篇文章先來說解一下匹配優先和忽略優先,什麼,你以爲很難?相信我,讀完這篇文章你確定能夠掌握的很好。不相信?那就讓我來帶着你試一試吧。git

在繼續下面的文章以前,咱們先來作個小練習題。那就是使用量詞匹配一個簡單的字符串,咱們如今假設這個字符串是"hello world",以下圖所示:github

"hello world"

有點正則表達式基礎的同窗很快就能夠寫出".*",很好,完美地匹配了咱們的測試字符串。正則表達式

成功匹配

那若是我將測試用例變爲"hello" "world",咱們會發現上面的正則表達式仍是能夠匹配整個測試用例,可是卻不是咱們想要的結果。咱們但願的是可以分別匹配"hello""world"而不是這個總體。app

那這個時候咱們須要如何修改上面的正則表達式,才能夠達到咱們想要的目的呢?其實很簡單,只須要在*後面添加一個?就能夠了。是否是很神奇呢?學習

".*?"

好,是時候展現真正的技術了。哦不,是時候跟你們解釋一下什麼是匹配優先,什麼是忽略優先了。測試

匹配方式的介紹:

首先咱們須要知道量詞都有哪些?基本的量詞有?(能夠匹配1次或者0次),*(能夠匹配無數次或者0次),+(至少須要匹配1次)。還有由大括號括起來的量詞,好比{2}(匹配2次), {2, 6}(匹配2到6次), {2, }(匹配至少2次)。
量詞默認是匹配優先的,若是在上面量詞(須要是可以表示範圍的量詞)的後面再添加一個?,那麼上面的量詞就變成了忽略優先的量詞,好比??*?+?spa

匹配優先:

匹配優先又叫作貪婪匹配,它的特色是,在量詞做用下的表達式會盡量嘗試匹配知足條件的字符,直到後面的字符串不知足這個表達式或者到達字符串的結尾。 只有在正則表達式總體在嘗試匹配卻沒有匹配成功的狀況下,匹配優先的這部分纔會歸還已經匹配的部分字符,好讓總體可以匹配成功。code

對於".*"來講,它的匹配過程以下圖所示:blog

".*"的匹配過程

  • 第一步:正則表達式的"開始匹配測試用例的第一個字符,發現測試用例的第一個字符也是",因而正則表達式中的"部分匹配成功。而後開始繼續下面的匹配。
  • 第二步:正則表達式的.*是一個總體,表示.能夠匹配無數次,或者0次。.是一個元字符能夠匹配任何字符(除了行的結束符),因此在遇到行結束符以前,這部分表達式對於接下來的字符都是能夠匹配成功的,就像上圖表示的那樣,一直匹配到這一行的結束。
  • 第三步:正則表達式的第三部分"須要在測試用例中可以匹配到",可是由於.*已經匹配到測試用例這一行的結尾了,因此爲了正則表達式的總體可以匹配成功,.*須要歸還已經匹配到的字符。在這個例子中,須要把最後匹配的"字符讓出來。讓正則後面的"這部分嘗試匹配,而後發現"能夠匹配讓出來的"字符,至此,整個匹配過程完成。

咱們發現,.*在匹配的過程當中讓出了一部分已經匹配的字符;這個過程咱們稱之爲回溯,這個會在之後的文章中跟你們詳細的講解一下。rem

關於匹配優先咱們其實能夠拿生活中的一些場景做類比。比如夏天到了,你比較喜歡喝啤酒,而後你會把你的冰箱裏面塞滿啤酒,雖然你很想再塞進去一些,可是冰箱的容積就那麼大(類比匹配到了字符串的結尾),因此你沒辦法再放更多的啤酒進去。這時候你想到只喝啤酒還不夠過癮,你還想吃點肉。因此你買了滷雞腿,而後把冰箱中的一些啤酒拿了出來(類比正則中的回溯,歸還已經匹配的字符),省出的空間用來放雞腿,而後這樣你以爲比較完美了(類比正則表達式匹配成功)。

忽略優先:

忽略優先又叫作懶惰匹配,它的特色是,在量詞做用下的表達式會盡量忽略掉知足條件的字符,只有在正則表達式總體在嘗試匹配卻沒有匹配成功的狀況下,忽略優先的這部分纔會去匹配知足條件的那些字符,好讓總體可以匹配成功。

對於".*?",它的匹配過程以下所示

  • 第一步:正則表達式的"開始匹配測試用例的第一個字符,發現測試用例的第一個字符也是",因而正則表達式中的"部分匹配成功。而後開始繼續下面的匹配。
  • 第二步:正則表達式的.*?是一個總體,表示.能夠匹配0次或者無數次,可是儘可能不匹配。因而,剛開始,.*?就什麼也沒有匹配
  • 第三步:正則表達式的"開始進行匹配,發現h不知足匹配,因而須要進行回溯。也就是.*?要嘗試匹配知足條件的字符,爲了後面的"可以匹配成功。因而.*?匹配了h,後面的"發現下一個字符是e,仍是不能夠匹配成功,而後再次進行回溯。一直到.*?匹配了hello,正則表達式的"發現此時後面的"是能夠匹配成功的,至此整個表達式匹配成功了一次。
  • 第四步:在接下來的字符串中,重複上述的1-3步驟,一直到字符串的結尾。

咱們能夠經過下面的圖來直觀的感覺一下。

".*?"的匹配過程

關於忽略優先,咱們也能夠拿生活中的一些場景做類比。好比你如今是一個在外地上大學的學生,你放假在家,如今開學了,你準備回到學校。這時候你的媽媽會讓你帶不少吃的用的和穿的。你雖然能夠帶這些東西,可是你不想帶這些大包小包的東西(類比懶惰匹配),感受很麻煩。可是你知道,若是你不帶一些去學校的話,你媽媽會生氣的(後面的"須要成功匹配)。因此你就拿了一些比較方便攜帶的,剩下的就不帶走了。這樣至少不會讓你媽媽生氣,你也不用帶那麼多東西,達到了雙方都還算滿意的結果(正則表達式匹配成功)

自測的練習題目

關於正則表達式量詞的匹配方式,咱們講解了匹配優先,和忽略優先的匹配方式。相信你們看過上面的文章以後,應該可以很好地掌握了。那咱們接下來就來作一些關於這兩種匹配方式的練習題。

  • 第一題:匹配一些簡單的HTML標籤

給出的測試用例以下:

<a>link</a> <span>hello</span><span>world</span> <button>click</button>

匹配的結果以下圖所示:

  • 第二題:匹配字符串中帶有¥前綴的格式化數字

給出的測試用例以下:

aaa¥100aaa
aaa¥a100aaa
aaa¥1a00aaa
aaa¥100.00aaa
aaa¥100,000,000.00aaa

匹配的結果以下圖所示:

若是你知道這兩道題目的答案的話,也歡迎在文章下面留言。你們能夠一塊兒探討一下,加深對本篇文章知識的掌握和理解程度。

關於正則表達式量詞匹配方式講解的上篇到這裏就結束啦,若是你以爲這篇文章對你有幫助的話,不要忘記點贊和轉發喲。若是你們有什麼疑問和建議均可以在這裏提出來。歡迎你們關注個人公衆號關山不難越,咱們一塊兒學習更多有用的正則知識,一塊兒進步。

公衆號

相關文章
相關標籤/搜索