(?<=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):

扫描二维码关注公众号,回复: 4762681 查看本文章
'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正则迷你书》

猜你喜欢

转载自juejin.im/post/5c2da434e51d45467145251a