例如: 12345 XD Hi12345678ab666666cd987654321
要找出: 12345678 和 666666;但不可以找出 987654321 中的 98765432 或者 87654321
於是我第一個想到的東西就是 Lookahead 和 lookbehind。
先來看一下如果直接使用 \d{6,8} 會取出什麼:Visual Regex Tester
可以看到,直接使用 \d{6,8} 是會連後方的 987654321 取出來。
最後我給的的解法是:(?<!\d)\d{6,8}(?!\d),結果:Visual Regex Tester
重點就在前面的 (?<!\d) 和後面的 (?!\d) 這兩個表示法,他們分別代表的是
negative lookbehind 和 negative lookahead
先來看 lookahead , 意思是「往前看」,語法為:
- Positive lookahead : X(?=Y)
- Negative lookahead : X(?!Y)
這邊要注意的是,要找的是 X , Y 只是附註條件,並不會被收納在 match group 中
實際例子: \d(?=[AB]) ,我要找一個數字,且後方必須是 A 或 B
因此這個字串:123A4C5B67 中,符合的只有 3 和 5;要注意,不是 3A 和 5B,是 3 和 5
結果:Visual Regex Tester
同樣的字串,若將 Pattern 改為:\d(?![AB]),則代表要找一個數字,且後方不能跟著A或B。如此一來符合的就是:123A4C5B67 中的: 1,2,4,6,7
結果:Visual Regex Tester
簡單來說可以想像類似於正規表示法中的 if 判斷,可以多多善用這個表示法。
-----
接著來看 lookbehind ,這邊要注意的是,並非所有程式語言都支援 lookbehind,我自己目前常用的程式語言中,似乎也只有 java 支援。(javascript 是不支援的喔)
lookbehind 就是向後看,同樣也分為 positive 和 negative:
- Positive lookbehind : (?<=Y)X
- Negative lookbehind: (?<!Y)X
同樣舉實際例子:(?<=[OP]).,要找任何一個字,且前方必須是O或P。或也可以這樣來稱呼:「尋找接再 O 或 P 後面的一個文字」
字串:AOIOOXPAOCKNJS ,符合的就是 I,O,X,A,C
結果:Visual Regex Tester
Negtive 就不多舉例,能理解就好。
-----
那麼回到最開始的表示法:(?<!\d)\d{6,8}(?!\d),來解釋看看這一段到底在找什麼東西。
先將其拆為:(?<!\d) \d{6,8} (?!\d) 三段,很快就可以看出,要找的東西是「6~8 個連續數字」,但是「前面不能有數字(Negative lookbehind)」以及「後面不能跟著數字(Negative lookahead)」。
由於 {6,8} 是 Greedy ,會盡量多取,因此就可以限制找到的數字數量是在 6~8 ,並且排除連續 9 個(以上)數字的部分了。
謝謝教學,相當清楚!
回覆刪除網址已失效
回覆刪除改用
https://regexper.com
謝謝,簡潔清晰的說明,獲益非淺
回覆刪除解釋相當清楚,謝謝
回覆刪除It's really clear. Thanks
回覆刪除非常感謝
回覆刪除感謝,非常實用!
回覆刪除簡潔清楚明瞭的說明,非常感謝
回覆刪除非常清楚, 感謝解惑!!
回覆刪除感謝解惑!!
回覆刪除