(?<=p)與:nth-child()的相似性分析
標題挺有意思吧,一個來自正則,一個來自css。
前者是正則斷言,後者是css選擇器。
正則是用來做什麼的?匹配字元的。 選擇器是用來做什麼的?匹配元素的。 既然都是用來“匹配”的,那麼如果有些地方有相似之處不足為奇。
我發現(?<=p)與:nth-child()就有很強的相似性,容我慢慢道來。
這裡假設讀者對css選擇器更熟悉些,所以下面的例子都是先css,後正則。
1. 匹配所有元素
假設頁面上有9個li,讓所有元素字型都變紅,這裡不會使用:nth-child的,直接用標籤選擇器就行了。
li{
color: red;
}
複製程式碼
同樣使用正則,也不需要使用(?<=p)。
'123456789'.replace(/./g, '*')
// "*********"
複製程式碼
2. 匹配第1個元素
匹配首個元素,css可以用:first-child
li:first-child{
color:red;
}
複製程式碼
正則可以使用^
位置匹配符:
'123456789'.replace(/^./g, '*')
// "*23456789"
複製程式碼
而我們知道:first-child是:nth-child特例:
li:nth-child(1){
color:red;
}
複製程式碼
此時,正則其實也可以用(?<=p):
'123456789' .replace(/(?<=^)./g, '*')
// "*23456789"
複製程式碼
(?<=^)
斷言其實匹配的是一個位置,^
之後的位置,當然還是開頭。可以參考《JS正則迷你書》對位置的講解。
3. 匹配第3個元素
css裡要匹配第3個元素,:nth-child(3)即可
li:nth-child(3){
color:red;
}
複製程式碼
而正則這邊呢?這裡需要轉個彎,要匹配第三個,其實是說前面還有2個:
'123456789'.replace(/(?<=^.{2})./g, '*')
// "12*456789"
複製程式碼
4. 匹配前3個元素
我們知道:nth-child選擇器厲害之處是在於它支援an+b表示式,比如匹配前三個:
li:nth-child(-n+3){
color:red;
}
複製程式碼
正則這邊就是說,要匹配的字元,前面有0到2個字元,
'123456789'.replace(/(?<=^.{0,2})./g, '*')
// "***456789"
複製程式碼
5. 匹配奇數位
css這邊使用2n+1
li:nth-child(2n+1){
color:red;
}
複製程式碼
正則這邊就是說,要匹配的字元,前面有0、2、4...個字元,
'123456789'.replace(/(?<=^(.{2})*)./g, '*')
// "*2*4*6*8*"
複製程式碼
類似的匹配偶數位,即要匹配的字元,前面有1、3、5...個字元:
'123456789'.replace(/(?<=^(.)(.{2})*)./g, '*')
// "1*3*5*7*9"
複製程式碼
6. 更一般的an+b
比如css這邊使用4n+3
li:nth-child(4n+3){
color:red;
}
複製程式碼
正則這邊就變成了,
'123456789'.replace(/(?<=^(.{4})*.{2})./g, '*')
// "12*456*89"
複製程式碼
7. (?=p)與:nth-last-child
我們知道:nth-child還有對應的:nth-last-child,即從後面數。比如要匹配後3個li:
li:nth-last-child(-n+3){
color:red;
}
複製程式碼
正則這邊呢?(?<=p)表示p後面的位置,它對應的是(?=p),表示p前面的位置。因此要匹配後3個字元:
'123456789'.replace(/.(?=.{0,2}$)/g, '*')
// "123456***"
複製程式碼
更多就寫了。
8. (?<!p)與:not(:nth-child())
在css中,要匹配除了第3個元素之外的所有元素可以配合:not
li:not(:nth-child(3)){
color:red;
}
複製程式碼
(?<=p)表示p後面的位置。而(?<!p)有點繞,它表示所有位置中,不是p後面的那個位置,或者說當下位置的前面不是p。
'123456789'.replace(/(?<!^.{2})./g, '*')
// "**3******"
複製程式碼
9. :nth-child(n+2):nth-child(-n+7)
:nth-child除了取反,還可以取交集,比如匹配第3-7個元素
li:nth-child(n+3):nth-child(-n+7){
color:red;
}
複製程式碼
(?<=p)也可以支援交集的
'123456789'.replace(/(?<=^.{2,})(?<=^.{0,6})./g, '*')
// "12*****89"
複製程式碼
交併補,還有並集,css很簡單:
li:nth-child(3),
li:nth-child(7){
color:red;
}
複製程式碼
正則呢,有|
就是來做這個:
'123456789'.replace(/(?<=^(.{2}|.{6}))./g, '*')
// "12*456*89"
複製程式碼
自此比較完了,結論是這二者非常像,很有意思。
本文完。 歡迎繼續閱讀本人的《JS正則迷你書》。