同事提出了一个需求,匹配1|1,但是有不能匹配-1|1,也就是1|1之前不能有-
代码如下
const reg = /[^-]1\|1/
reg.test("1|1") // true
reg.test("-1|1") // false
reg.test("-1111|1") // true
由此我和我的小伙伴们又去找了些其他奇奇怪怪的需求~比如
// 相邻两个数字不重复
const siblingNum = /(\d)\1/ // 这个是找到相邻数字重复的情况,
siblingNum.test("112") // true, 取反就是false,也就是没有找到相邻数字重复的情况
// 所有的数字不重复
const noRepeat = /^(?:(\d)(?!.*?\1))+$/;
noRepeat.test("123") // true
noRepeat.test("1231") // false
在这里面知识点还挺多。
-
对于^的使用,我一直认为他是起始符,没想到他还有第二个作用,[ ^abc ]:负值字符集合。匹配未包含的任意字符。可以匹配abc以外的字符
-
\1,知识不足的我原以为只有在匹配结果中才能用$1来取到第一个括号里的数据,现在才知道在正则表达式中可以使用\1来取出第一个括号中的数据,这里需要注意一点是第一个括号。
比如/(\d)\1/
和/((\d)\1)/
这两个是完全不一样的,第一个里面第一个括号包含的只有\d,而第二个则是(\d)\1,所以运行结果也是不一样的,
第二种我也不知道她能匹配啥,我对他的理解应该是一个错误写法,因为\1取出来的是包含\1的,所以会是一个循环嵌套,感觉应该是出错的,希望有人能帮帮我~ -
?: 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。
例子:上面/((\d)\1)/
想改造成/(\d)\1/
的结果,可以这么写:/(?:(\d)\1)/
这样表达式就不会匹配最外面那个括号了,第一个括号就变成\d外面的括号了,这样就跟/(\d)\1/
一样了。 -
?! 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。
先提供一下别人的例子
例如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。根据我的实验,我对他的理解是这样的:(还是基于上面的例子)
他只能匹配Windows后面不是95|98|NT|2000的字符串中的Windows字段
对于(?!.*?\1)
这一段表达式,我想把他拆开看,首先是?!,然后是.*,并对他进行?处理,也就是可有可无,最后是\1,也就是应对前面的(\d)。
先看后面的 .*?\1,这一块应该是匹配当前元素之前所有的可匹配的字符,例如123451,(\d)(.*?\1),匹配的应该就是123451,\d先匹配到1,然后\1就代表了1,然后.*?就代表了2345。
然后在加上?!,也就是说不匹配后面再次出现当前字符的情况,如果没有出现,当前字符才算匹配成功。
以上就是我对正则的一点理解,记下来,以防后面忘记,如果有哪里写错了,请大家尽情的鞭挞我吧~感谢^_^
参考文献:
https://www.runoob.com/regexp/regexp-metachar.html
https://www.cnblogs.com/youxin/p/3546657.html
https://www.cnblogs.com/dogecheng/p/11466687.html