1. 程式人生 > >(?<=p)與:nth-child()的相似性分析

(?<=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正則迷你書》