什么是正则表达式

正则表达式(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 - 1eg: /\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'].