概念先行。
正则表达式:又称规则表达式。常用于检索,替换符合某种符合(规则)的文本。
组成:普通字符和元字符,普通字符就是一个普通的查找串,如abc,原字符具有特殊含义。
这里研究的是JavaScript的正则,还有一个修饰符的概念。
最简单的正则表达式就像一个查找字符串。
语法: /正则表达式主体/修饰符(可选)
如:
1 const str = 'testings' 2 3 cosnt patt = '/testing' 4 5 // test是正则表达式方法,用于检测一个字符串中是否匹配某个模式(正则),有则true,否则false 6 patt.test(str) // ture
这里先不深究方法
元字符:
之前觉得其似懂非懂在于元字符的多其杂,又没有下功夫就深究(这是重点)。
-- 开始
: 将下一个字符标记符、或向后引用、或一个八进制转义符。常见于,\ 匹配 , \n 匹配 ,和一些字符搭配会产生一些预定义模式,如 d 表示查找数字,等同于[0-9], 活用转义能够达成很多复杂的情况。
-- 定位符
^ : 1、限定开头,如 /^a 匹配a开头的的字符串,如匹配abc,而不会匹配bca。 2、 取反, 当这个字符出现在一个字符集合模式中,意义则不同了,如 [^0-9],匹配除了0到10以外的所有字符。
$ : 匹配输入的行尾, 即限定行尾。如: /a$ 匹配 bca中的a,而不匹配abc中的a
两个预定义的模式
: 匹配一个单词边界,如字与空格直接的位置。如/ble,匹配in posible xxx中的ble。不匹配ablexxxx中ble。因为不是在单词边界。与$不同是$是行尾。
B: 匹配非单词边界。与上面相方。
注意:定位符和限定符不能连在一起使用。如^+,会报错.
-- 限定符
* :匹配前面子表达式(注意是表达式)的任意次。等价于 {0,}。 如:ab* 可以匹配a,也可以匹配ab, abb。/a(bc)*,那就是a可以,abc可以,abcbc可以
+:匹配前面子表达式一次或者更多,(大于等于1)等价于{1, }。/ab+ 可以匹配ab,abb,无法匹配a
?:匹配前面子表达式零次或者一次, 等价于{0,1}。如: /ab? 匹配ab中a,ab。ac中a也是匹配的
限定符中的+和*都是贪婪匹配的,即能匹配多点就匹配多点。如/a+,能匹配baad中的aa,也不只匹配a。所以有 ?(不是上面那个的意思),加在限定符的后面。表示不贪婪匹配。
如果是这样: /a+?,那么baaaad中,只匹配a,即结果为a, 而不匹配更多。
1 // 举个有趣的栗子 2 <p>hello,world</p> 3 4 // 正则 /<.*> 5 // 会直接匹配整条式子。 6 <p>hello,world</p> 7 8 // 如果加上?, 即/<.*?> 9 // 匹配结果为 10 <p>
-- 三种括号
--- 大括号 {}
{ : 标记限定符表达式的开始,和 } 搭配。如:{n},{n,}, {n,m}
{n} : n是一个非负整数,匹配确定的n的次数。如:a{3},匹配aaa,也匹配baaad中的aaa,限定死次数。
{n, }: n是一个非负整数,匹配至少n次,后一个参数为空,表示无限。如:a{1,} 匹配a, 也可以匹配aa,aaa, baaaa, baaaad这里。
{n, m}:m和n都是一个非负整数,圈定一个范围。最少匹配n次,最后匹配m次。如:{1,3}就是最少匹配一次,最多匹配3次。
--- 小括号 ()
():表达一个子表达式的开始和结束位置,专业名词为(组)。如:/a(ab)+,匹配a, aab。甚至可以混合一起来,/(ab){1,2}, 匹配ab,abab。甚至更多更多的混合,以达到目的。
--- 中括号[]
[]:表示字符集合,这点和小括号常容易弄混,如[abc],可以匹配a,可以匹配b一样。piano也能匹配其中的a。同时还可以使用-作为连接符号,如[0-9]表示匹配0到9的数字,
-- 其他
. : 匹配除了换行 和 之外的任意字符。如果想匹配换行,可以使用[sS]这种模式。
| :或,匹配或者是那个 /z|foo,匹配z或者foo。混搭如:/[z|f]oo,匹配zoo或者foo。
注:由于上诉都是特殊字符,有其特殊的含义,所有需要匹配上面的字符的时候,都需要增加转义,如: /+,来匹配+这个字符。
-- 非打印字符(比较僻)
非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列
cx:匹配由x指明的控制字符。例如, cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。(真的很少用)
f: 匹配一个换页符。等价于 x0c 和 cL。
: 匹配一个换行符
:匹配一个回车符
s:匹配所有空白字符。包括空格,换页符,制表符
S:匹配任何非空白字符。
:匹配一个制表符。
v: 匹配一个垂直制表符。等价于 x0b 和 cK。
-- 常用预定义模式
经常用字母来使用预定义模式,而该模式的大写往往是小写含义的相反。下面四个是常用的。
d: 匹配一个数字字符,等价于[0-9]
D: 匹配一个非数字字符,等价于[^0-9]
w: 匹配字母,数字,下划线。等价于[A-Za-z0-9_]。
W:匹配非字母,数字,下划线。等价于[^A-Za-z0-9_]。
运算符优先级:(上到下,高到低)
: 转义 (1)
(),[]:圆括号和方括号 (2)
*,+,?{n}: 限定符 (3)
^,任意元字符,$,任意字符 (4)
| : 或 (5)
修饰符:
javasript中正则表达式有个修饰符的概念。
ES6前有3个,分别是i, g, m
i: 执行对大小写不敏感
g:执行全局匹配(而非找到第一个字符串后就停下)
m: 执行多行匹配
ES6后增加了几个修饰符 u, y, s
u: ES6 对正则表达式添加了u
修饰符,含义为“Unicode 模式”,用来正确处理大于uFFFF
的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码。这里有个概念,ES5前是不支持大于uFFFF的 Unicode 字符。JavaScript会将其认为是两个字符,这会导致一些问题。增加u,就能正确处理了
y: 这个也是ES6的新概念,名称为粘连。和g一样都是全局匹配,不同是g是剩余位置只有有匹配就可以继续匹配。但是y限制必须从上一个结尾的位置有匹配才继续匹配。
如:
1 const s = 'aaa_aa_a' 2 3 const pattone = /a+/g 4 const patttwo = /a+/y 5 6 pattone.exec(s) // aaa 7 patttwo.exex(s) // aa 8 9 10 pattone.exec(s) // aa 11 patttwo.exex(s) // null
s: dotALL模式,匹配任意单个字符。应对于正则中的点.元字符,无法匹配换行的情况,上面我们可以用其他方法解决,ES6提出一种方法。就是添加s修饰符。
如:
1 const patt = /hello.word 2 3 patt.test(‘hello word’) // 中间有 换行,匹配false 4 5 使用s修饰符 6 7 /hello.word/s.test(‘hello word’) // 成功
文章很长,谢谢阅读。
讲点题外话,说起正则表达式,对其是又爱又恨,之前收录过一篇常用正则表达式,实际上也只是收录常用的语法,但实际上重头写一个复杂的正则表达式却写不出,所以决定来从头碰一碰他,发现其实很有魅力。
代码这种东西真是一碰就停不下来。
最后一句,热爱可挡岁月漫长,与君共勉。