問題: 有字串:「python php ruby javascript jsonp perhapsphpisoutdated」
對於該字串,使用純正則取得 所有帶p 但是不能包含ph 的單字
輸出數組 [ 'python', 'javascript', 'jsonp' ]
這個問題想了比較久,也沒思路
我的解法是
<code>var result = str.match(/\b\w*(?=p)\w*\b/g) .filter((value)=>!/.*(?=ph)/.test(value)) var result2 = str.match( /\b((?!ph|\s).)*((p[^h\s]((?!ph|\s).)*)|p)\b/g ) console.log(result2)</code>
但是不符合純正則的要求
群裡有大牛給了這麼一個答案
<code>/\b((?!ph|\s).)*((p[^h\s]((?!ph|\s).)*)|p)\b/g </code>
完美運行
但是我看不懂,希望有大牛能幫我解讀
問題: 有字串:「python php ruby javascript jsonp perhapsphpisoutdated」
對於該字串,使用純正則取得 所有帶p 但是不能包含ph 的單字
輸出數組 [ 'python', 'javascript', 'jsonp' ]
這個問題想了比較久,也沒思路
我的解法是
<code>var result = str.match(/\b\w*(?=p)\w*\b/g) .filter((value)=>!/.*(?=ph)/.test(value)) var result2 = str.match( /\b((?!ph|\s).)*((p[^h\s]((?!ph|\s).)*)|p)\b/g ) console.log(result2)</code>
但是不符合純正則的要求
群裡有大牛給了這麼一個答案
<code>/\b((?!ph|\s).)*((p[^h\s]((?!ph|\s).)*)|p)\b/g </code>
完美運行
但是我看不懂,希望有大牛能幫我解讀
<code>var str = 'python php ruby javascript jsonp perhapsphpisoutdated'; var reg = /\b(\w*(p[^h\s](?!ph))\w*)\b/g; str.match(reg); // => ["python", "javascript", "perhapsphpisoutdated"]</code>
b
為邊界字符,範圍為w
和W
之間的字符。
()
標識的是子表達式。
(?!)
標識的是反向先行斷言,和子表達式不同是先行斷言並不會被記錄。
[^]
標識的是取不符合條件的集合
所以上面的正則意思為取邊界之間的含有‘p’但是後面緊跟的字符串不是‘h’或‘空格’,同時後面也不含有‘ph’的字符串
b((?!ph|s).)*((p[^hs]((?!ph|s).)*)|p)b/g
b
是邊界字元
所以每一個字對應的配對是:((?!ph|s).)*((p[^hs]((?!ph|s).)*)|p)
把這個表達式拆成三個部分:
((?!ph|s).)*
(p[^hs]((?!ph|s).)*)
p
表達式裡出現最多的是 ((?!ph|s).)*
讓我們來分析一下
《javascript權威指南》裡講:
(?!p)
是零寬度負向先行斷言,表示接下來的字符不與p
匹配
這裡的 零寬度 是指 它本身不佔用匹配:
可能這一點比較難理解,舉個例子,比如:
計算"1234".match(/((?!34).)*/)
的值
第一次(?!34)
之前沒有東西、忽略,只對.
進行匹配,匹配到"1"
,字符串剩餘"234"
對"234"
進行匹配,測試"23"
是否匹配?!
裡的"34"
,結果不匹配,繼續進行,"23"
"34",結果不匹配,繼續進行,
"23"🟎"沒有被消耗,接下來的.
配對到
對
"34"
進行匹配,由於"34"
匹配?!
裡的
整個表達式的匹配結果是"12"
之前的部分p
結論:
/((?!p).)*/
形式的表達式匹配到的字串是
第一個表達式表示匹配單字中
第二個表達式匹配單字中
"p"
及之後的字符,要求"p"
之後的第一個字符不能為"h"
,並且同樣要求不匹配到
第三個表達式匹配單獨的
"p"
字符,因為之前的匹配中最短能匹配到的形式是
梳理一下就會發現,上面的匹配的三個表達式都不匹配 "ph"
, 但其中一定會有