标题挺有意思吧,一个来自正则,一个来自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正则迷你书》。