什么是正则表达式
正则表达式(regular expression)
描述了一种字符串匹配的模式(pattern)
,可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为”元字符”)组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
正则表达式的创建
正则表达式是引用数据类型,又称规则表达式。可以通过内置构造函数创建,亦可以通过字面量方式创建。
字面量方式创建
语法:
const reg = /xxx/
双斜杠包夹的内容就是正则表达式。
内置构造函数创建
语法:
const reg = new RegExp('xxx')
通过new
关键字创建正则实例。
so:
如果写一个正则表达式xxx
,来先了解正则表达式的一些比较特殊的符号意义所在?
元字符
\d
出现一个数字
const reg = /\d/;
const str = 'sdasdna126sdfd6550sad';
const res = reg.test(str); // true
其他字符同理,就不单独写例子了,通过test
则返回true
.
\D
出现一个非数字
\s
出现一个空格
\S
出现一个非空格
\w
出现一个数字字母下划线
\W
出现一个非数字字母下划线
.
出现一个除了换行以外的字符
实际使用过程中,称之为任意字符也不为过。
限定符
*
出现的次数为
0 - infinite
(正无穷),eg.
/a*/
表示出现 0 - 无穷次(因为限定的次数最低可以是 0,所以理解为所有字符亦可)😂😂😂
+
出现的次数为
1 - infinite
(正无穷),eg.
/\d+/
表示数字出现一次以上
?
出现的次数为
0 - 1
,eg:
/\d?/
可以不出现数字,也可以出现数字(仅匹配出现的第一次)
{n} 和 {n,}
单类型字符连续出现
n
个,eg.
/\d{3}/
表示连续三个或三个以上数字在一块 ,只要出现一次即为true
.
{n,m}
单类型字符连续出现至少
n - m
次(意味着也可以超过),eg.
const str = 's354ada1sdf22515553sg4d5sf';
console.log(/\d{5,7}/.test(str)); // true
估计有些童鞋已经蒙圈了,既然都是至少这么多次,那它们直接有啥区别?比如{n,} {n,m}
,又该怎么使用?,别急来先看边界符:
边界符
写了边界符后,在使用test
检测时,搭配限定符,就可实现区分{n, m} 和 {n, }
,前者代表整个长度只能在n - m
,后者是长度至少为n
.
^ 以...开头
$ 以...结尾
const reg1 = /^\d$/;
const str1 = '1';
const str2 = '123';
console.log(reg1.test(str1)); // true
console.log(reg1.test(str2)); // false(\d只能出现一个)
const reg2 = /^\w{4,9}$/;
const str3 = '_as123';
const str4 = '_as1234567';
console.log(reg2.test(str3)); // true
console.log(reg2.test(str4)); // false(指定了\w 出现4-9次 长度 字符串长度不能超过 9,同时 只能是\w字符)
特殊符号
\
转译符
意指把 原本没有特殊含义的东西 加上 \就没了特殊含义;把原本就有特殊含义的东西加上\
就没有特殊含义了
()
把一块东西当成整体
|
或
注意:
||
逻辑或|
占位或 两者的区别
eg.
简版邮箱/^\w{6,12}@(qq|163|sina)\.(com|cn|net)/
[]
取中间任意一个
只能取中括号内的一个字符,注意字符长度,eg.
const reg = /^[abcd]$/;
const str = 'a';
const str2 = 'abcd';
console.log(reg.test(str)); // true
console.log(reg.test(str2)); // false
-
到..至..
eg.
对于正则 /^[a-zA-Z0-9_]$/
,字符M
就符合.
[^]
非
对[]
的正则取非,eg. /^[^a-z]$/
,指非a-z
的字符,长度为 1.
再然后要说的就是标识符了,它写在//
的后面,具体使用如下:
标识符
g
全局匹配,i
忽略大小写,eg.
const reg = /m/gi;
let str = 'MasnonasmsdfMasm';
str = str.replace(reg, '*');
console.log(str); // *asnonas*sdf*as*
当然标识符不仅仅是上面介绍的这两个,https://regex101.com/可以在这个网站上测试及学习…
正则表达式原型上的方法
eg.
正则表达式reg = /xxx/
.
对字符串进行验证
reg.test(str)
. 符合规则就返回true
否则返回false
.
const reg = /abc/;
const str = 'ahsjdhaabbc';
const res = reg.test(str); // false
捕获字符串里面符合规则的内容
reg.exec(str)
第一次是从头开始匹配,如果找到符合规则的字符,那么返回一个数组,数组的第 0 项就是捕获到的符合规则的字符,第二次应该从第一次结束的位置开始捕获,如果找到也是返回一个数组,如果没有找到符合规则的字符,就返回一个null
,下次执行又是从头开始重新捕获.(用的很少)
数据转换
reg.toString()
将正则表达式转换为字符串。
字符串与正则相关方法
字符串基于正则完成替换
str.replace(regexp|substr, newSubStr|function)
. reg:
一个RegExp
对象或者其字面量,该正则所匹配的内容会被第二个参数的返回值替换掉(该方法的具体参数使用请参阅文档,这里仅介绍正则相关)
const reg = /m/gi;
let str = 'MasnonasmsdfMasm';
str = str.replace(reg, '*'); // *asnonas*sdf*as*
和replace
相近的还有replaceAll
,与前者差别就是后者匹配所有符合正则的子串并替换,而前者则需要通过指定g
参数实现。
提取字符串中符合正则的匹配项
str.match(reg)
返回一个数组,将所有符合的子串提取出来。
const str = 'Ma123sdf4565dsfsdf789sdf35';
console.log(str.match(/\d{2}/g));
// ["12", "45", "65", "78", "35"]
查找符合规则的字符串子串
str.search(reg)
查找符合规则的字符,返回相对应的下标,如果有多个符合,那么就返回第一个,作用同indexOf
,不过后者无法传入reg
正则查找.
贪婪模式和非贪婪模式
在javascript
中的正则表达式的匹配方式默认是贪婪模式。
eg.
贪婪模式
// 指匹配 b 开头,后续出现 0 -任意次数的 a 的子串
const reg = /ba*/g;
const str = 'baaaabab';
console.log(str.match(reg)); // ['baaaa', 'ba', 'b']
正是因为贪婪匹配(尽可能多的匹配符号条件的子串),导致了匹配出的第一项是baaaa
(从前向后匹配,一直到匹配到的字符串不符合条件时停止), 而非b
.
非贪婪模式
当然有贪婪也就有非贪婪,如何指定?
使用字符
?
标识正则使用非贪婪模式进行匹配(这是?
的另外一种用法含义)看你怎么理解
对上面例子的正则改造一下:
const reg = /ba*?/g;
const str = 'baaaabab';
console.log(str.match(reg)); // ['b', 'b', 'b']
/ba*
为原有的正则表达式,在其后添加?
指明非贪婪,匹配到的结果自然就是['b', 'b', 'b']
.
以为这样就结束了?no no no...
正则在匹配时还有另外一条规则…比贪婪规则的优先级更高,so
在你使用时,如果不注意…你会怀疑自己的…
匹配的优先级
最先开始的匹配拥有最高的优先权 —— The match that begins earliest wins。
怎么解释,匹配优先匹配左边的第一个字符,然后尽可能少的去匹配后续字符,而不是忽略第一个字符,去找第二个…😋😋😋 匹配结果不会从左侧缩减字符,而只会进行右侧的懒惰匹配 eg.
const reg = /a*?b/g;
const str = 'baaaabab';
console.log(str.match(reg)); // ['b', 'aaaab', 'ab']
如果你未理解该规则,那么按照非贪婪的理解,打印的结果应该是['b', 'b', 'b']
,这是错误的.
正确结果应该是['b', 'aaaab', 'ab']
.