每天資訊距離弄懂正則的環視,你只差這一篇文章

菜單

距離弄懂正則的環視,你只差這一篇文章

上一篇文章《正則表示式匹配素數的原理講解》寫完之後,一些同學給我留言說對於正則表示式的

「環視」

不是很理解;希望我能夠講解一下關於環視部分的內容。那麼這篇文章的目的就是幫助大家理解什麼是環視,環視有什麼作用,以及在實際的開發中的一些例子。

「相信閱讀本文之後,大家對於正則的環視會有更深入的理解。」

正則表示式的環視是什麼

環視顧名思義就是

「環顧四周,向左看看向看看,找一個合適的位置」

。環視

「匹配的是一個位置而不是字元,這點尤為重要。」

那麼我們是怎麼找到這個合適的位置的呢?當然是根據環視裡面包含的條件去尋找這個位置。接下來我會用生活中的一些場景來解釋每一種環視。

肯定的順序環視

假如你現在是一名叫張三的學生,現在是體育課需要大家排個隊,你記性不好忘記了自己之前的位置,但是你還記得你的後面是李四。所以這個時候你肯定

「先找到李四,然後站在他的前面就可以了」

。所以你這個選擇背後的邏輯是,

「我站的這個位置後面需要是李四才可以」

,我們可以用下面這個圖來表示你的選擇。

距離弄懂正則的環視,你只差這一篇文章

(?=李四)

如果我們使用正則表示式來表示這個位置的話,那就是(?=李四),這就表示了你想要找的位置。

首先解釋一下什麼是

「順序環視」

,什麼是

「逆序環視」

。因為正則表示式的匹配過程是從左到右的,所以如果我們要

「判斷一個位置的右邊滿不滿足某個條件,這就叫順序環視」

。如果我們

「判斷一個位置的左邊滿不滿足某種條件的話,這就叫做逆序環視。」

你可能會覺得上面這個正則表示式有點難記,首先我們需要知道

「環視都是以(?作為開頭的,然後接下來的一到兩個符號表明是那種環視,再然後就是需要滿足的條件,最後是一個)表示結束。(?=條件)可以這樣理解,?表示疑問,=表示是否滿足匹配。也就是當前位置是否滿足給出的條件。」

我們來實踐一下吧,假如b表示李四,你能否找出張三需要站的位置呢?

距離弄懂正則的環視,你只差這一篇文章

(?=b)

否定的順序環視

假如你現在是一名叫張三的學生,現在是體育課需要大家排個隊,但是你不想讓李四站在你的後面,因為他總是喜歡用中性筆在你的後背上亂塗亂畫。所以這個時候你會怎麼選擇位置呢?你肯定先看一個位置,只要這個位置的後面不是李四就可以了。

「因為就算李四在你前面也無所謂,畢竟他不能畫你的後背了。」

所以你做這個選擇背後的邏輯是,

「只有你站的這個位置後面不是李四才可以」

。我們可以用下面這個圖來表示你的選擇。

距離弄懂正則的環視,你只差這一篇文章

(?!李四)

上面這個位置可以用正則表示式(?!李四)來表示,作為程式開發者,我們對!很熟悉,在這裡也是同樣的意思。

「表示不能夠滿足後面的條件。」

我們來實踐一下吧,假如b表示李四,你能否找出張三需要站的位置。

距離弄懂正則的環視,你只差這一篇文章

(?!李四)

肯定的逆序環視

假如你現在是一名叫張三的學生,現在是體育課需要大家排個隊,你記性還是很不好忘記了自己之前的位置,但是你還記得你前面是李四。所以這個時候你肯定先找到李四,然後站在他的後面就可以了。所以你這個選擇背後的邏輯是,

「我站的這個位置前面需要是李四才可以」

。我們可以用下面這個圖來表示你的選擇。

距離弄懂正則的環視,你只差這一篇文章

(?<=李四)

如果我們使用正則表示式來表示這個位置的話,那就是(?<=李四),這就表示了你想要找的位置。

「(?<=條件)可以這樣理解,?表示疑問,<表示方向是當前位置的左邊,=表示是否滿足匹配。也就是當前位置的左邊是否滿足給出的條件。」

我們來實踐一下吧,假如b表示李四,你能否找出張三需要站的位置。

距離弄懂正則的環視,你只差這一篇文章

(?<=b)

否定的逆序環視

假如你現在是一名叫張三的學生,現在是體育課需要大家排個隊,你是一個比較調皮的孩子,總喜歡在李四的後背上亂塗輪畫。現在老師說你站在那裡都可以,但是就是不可以讓李四站在你的前面。

這時候你該如何選擇,你肯定先找一個位置,然後確定你前面不是李四就可以了。

「哪怕李四在你的後面,你也不能夠在李四的後背上亂塗亂畫了」

所以你這個選擇背後的邏輯是,

「我站的這個位置前面不能夠是李四才可以」

。我們可以用下面這個圖來表示你的選擇。

距離弄懂正則的環視,你只差這一篇文章

(?<!李四)

如果我們使用正則表示式來表示這個位置的話,那就是(?<!李四),這就表示了你想要找的位置。(?<!條件)可以這樣理解,?表示疑問,<表示方向是當前位置的左邊,!表示不匹配。

「也就是當前位置的左邊不能夠匹配給出的條件。」

我們來實踐一下吧,假如b表示李四,你能否找出張三需要站的位置。

距離弄懂正則的環視,你只差這一篇文章

(?<!b)

如果你看到得了到這裡,那麼你應該知道了這四種環視的表示方法,和它們表示的含義了。接下來我們來看一下環視在實際開發中的應用吧。

環視在實際開發中的應用

數字千分位的處理

在實際的開發中,作為一個前端,經常需要把原始資料處理的美觀一些,然後再展示給使用者,數字的千分位新增逗號就是一個很常見的需求。

這個問題的解決方案有很多種,使用正則表示式來解決這個問題是個很不錯的方案。而且這個正則表示式要使用到我們今天學習的環視。那麼我們該怎麼使用環視去解決這個問題呢?

當我們使用正則表示式去解決問題的時候,第一件事情就是需要明確解決的是一個什麼問題。對於這個問題來說,我們要解決的問題是匹配一些位置。什麼位置?就是一個數字,

「從後向前數,每隔三個數字的位置,並且每個位置的左邊都需要有數字。」

當我們明確了我們需要解決的問題之後,我們就可以寫我們的正則表示式。首先寫一個能夠匹配每隔三個數字的位置。這個比較容易我們可以使用

「肯定的順序環視」

,(?=\d{3})應該是我們比較容易想到的。這個正則表示的意思就是

「匹配一個位置,這個位置的後面需要是三個數字」

。我們可以看一下我們匹配的結果。

距離弄懂正則的環視,你只差這一篇文章

(?=\d{3})

滿足上面條件的位置有好幾個,但是有一些不是我們想要的。比如5和6之間的位置就不是我們想要的,但是因為這個位置後面是678,也滿足我們上面的正則表示式,所以是能夠匹配的。那麼我們應該如何排除這些不想要的位置呢?

還有一個隱藏的條件,那就是我們還需要

「匹配字串的結尾」

。如果我們把上面的正則表示式修改為(?=\d{3}$),這樣就限定了我們匹配的位置,

「這個位置的後面是三個數字,然後就是字串的結尾」

。我們看一下這個表示式的匹配結果。

距離弄懂正則的環視,你只差這一篇文章

(?=\d{3}$)

當我們限定了最開始匹配的位置之後,現在就找到了一個正確的位置。但是還沒有達到我們的要求,我們還需要找到3和4之間的位置。這個時候我們可以使用量詞來解決這個問題,我們知道3和4之間的位置距離字串的結尾有6個數字,是3的倍數,所以我們需要能夠匹配數字的個數是3、6、9等,只要是3的倍數就可以。所以我們可以將上面的表示式修改為(?=(\d{3})+$),

「+作用於前面括號括起來的\d{3},表示至少需要有一個\d{3}」

。我們來看一下這次表示式的匹配結果。

距離弄懂正則的環視,你只差這一篇文章

(?=(\d{3})+$)

這次的匹配結果好像還有點問題,那就是數字的開頭也被匹配了,但是這不是我們想要的結果。那麼我們應該怎麼處理呢?一些同學可能會說,我們只要保證每一個的位置左邊至少有一個數字就可以了。嗯,這個方法也是可以的,按照這個思路,我們會寫出下面的正則表示式(?<=\d)(?=(\d{3})+$)。

「(?<=\d)是肯定的逆序環視,表示當前位置的左邊需要是一個數字」

。我們來看一下這個正則表示式的匹配結果。

距離弄懂正則的環視,你只差這一篇文章

(?<=\d)(?=(\d{3})+$)

這次這個正則表示式終於滿足了我們的需求,匹配出了正確的位置。如果你覺得上面的正則表示式有點長的話,我們還可以使用\B來替換掉(?<=\d)。結果也是一樣的,聰明的你知道為什麼嗎?在文章下面留言跟大家一起分享你的見解吧。

關山不難越