首先要明白正则表达式可以干什么?

正则表达式是用于匹配字符串中字符组合的模式。简单的说就是比如你想知道一串数字是否是正确的手机号。就需要用到正则表达式。由于之前一直对正则表达式的知识比较薄弱,所以在此进行查缺补漏

一、创建一个正则表达式

创建一个正则表达式的方法有两种:

字面量创建;

1
const regTest = /[a-z]/

使用构造函数创建

1
const regTest = new RegExp('[a-z]')

这里就使用第一种简单字面量的方式来熟悉正则表达式相关知识。正则表达式的匹配方法有很多例如 exex()、test()、match()等。这里主要熟悉正则的编写,方法先不做介绍。能看懂下面的匹配方法就行

1
2
3
const helloReg = /Hello/
const str = 'Hello World'
helloReg.test(str) // true

二、正则表达式修饰符

修饰符是在字面量的结尾加上的参数。或是用构造函数创建的对象第二个参数。如:new RegExp('[a-z]', i);

修饰符 描述
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。

三、正则表达式中的特殊字符

断言类

表示一个匹配在某些条件下发生。断言包含先行断言、后行断言和条件表达式。

特殊字符 含义
^ 匹配输入的开头。(或对后面的校验取反)
$ 匹配输入的结束。

字符类

区分不同类型的字符,例如区分字母和数字。

特殊字符 含义
. 默认匹配除换行符之外的任何单个字符。例如,/.n/ 将会匹配 “nay, an apple is on the tree” 中的 ‘an’ 和 ‘on’,但是不会匹配 ‘nay’。
\b 匹配一个单词的边界,即匹配两边中的一边没有其他元素或者空格。例如:/123\b/匹配’123 456’中的’123’
\B 匹配非单词边界,例如/\Bpple/匹配”apple”中的“pple”
\d 匹配任何数字(阿拉伯数字)。 相当于 [0-9]. 例如, /\d//[0-9]/ 匹配 “B2is the suite number”中的“2”。
\D 匹配任何非数字(阿拉伯数字)的字符。相当于[^0-9]. 例如, /\D/ or /[^0-9]/ 在 “B2 is the suite number” 中 匹配 “B”.
\n 匹配换行符。例如/\n/g匹配”I am a boy. \n “中的换行符
\w 匹配基本拉丁字母中的任何字母数字字符,包括下划线。相当于 [A-Za-z0-9_].
\W 匹配任何不是来自基本拉丁字母的单词字符。相当于 [^A-Za-z0-9_].
\s 匹配空白字符。例如/\s/g匹配”I am a boy”中的所有空格
\S 匹配非空白字符。例如/\S/g匹配”I am a boy“中的所有字母

量词类

量词表示要匹配的字符或表达式的数量。

特殊字符 含义
x* 将前面的项“x”匹配 0 次或更多次。等价于 {0,}例如/bo*/匹配“A ghost booooed”中的“boooo”
x+ 将前一项“x”匹配 1 次或更多次。等价于{1,}。例如,/a+/匹配“candy”中的“a”和“caaaaaaandy”中的“a”。
x? 将前面的项“x”匹配 0 或 1 次。等价于 {0,1}
x{n} 其中“n”是一个正整数,与前一项“x”的 n 次匹配。例如,/a{2}/ 不匹配“candy”中的“a”,但它匹配“caandy”中的所有“a”,以及“caaandy”中的前两个“a”。
x{n,} 其中,“n”是一个正整数,与前一项“x”至少匹配“n”次。例如,/a{2,}/不匹配“candy”中的“a”,但匹配“caandy”和“caaaaaaandy”中的所有 a。
x{n,m} 其中,“n”是 0 或一个正整数,“m”是一个正整数,且 m > n 至少与前一项“x”匹配,最多与“m”匹配。
?=n 匹配任何其后紧接指定字符串 n 的字符串。例如/is(?= all)/g 匹配 “There is all” 中的 “is all”
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。例如/is(?! all)/gi 匹配 “Is there all?” 中的 “Is“

括号类

括号 含义
() 小括号用于对字符或元字符进行分组以及表示可选择性。如(A\d){1,3}和(red|green)
[] 方括号用于查找某个范围内的字符。例如[0-9]、[a-z]、[A-D]
{} 大括号用于标记限定符表达式的开始。如n{1,9}匹配 X 至 Y 个 n 的序列的字符串。

四、实现几个常用的正则表达式

手机号

手机号的校验分为以下几个部分:

①11 位数字,不能多也不能少;得到如下/\d{11}/

② 第一位数字必须为 1,第二位为 3,4,5,6,7,8,9 中的一个;得到

1
/^1[3-9]{1}\d{9}$/

③ 注意不要忘了用上^匹配开始和$匹配结尾。不然超过 11 位的也会被校验成功

身份证号

身份证号的校验分为以下几个部分:

① 地区的前两位为省级;第一位为 1-9,第二位为 0-9;三四位为市级,五六位为县级。得到[1-9]{1}\d{5}

② 出生年月日一共 8 位;年份从 18XX 开始,到目前 20XX(看到网上很多是校验到 3XXX,这里以我个人的理解先校验到 20XX);得到如下(18|19|20)\d{2}

月份 01~12;((0[1-9])|(10|11|12))

日期 01~31;((0[1-9])|1\d{1}|2\d{1}|3[01])

③ 顺序码;\d{3},校验码(\d|X|x)

④ 最后讲上面所有的检验结合得到如下:

1
/^[1-9]{1}\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))((0[1-9])|1\d{1}|2\d{1}|3[01])\d{3}(\d|X|x)$/

当然光靠正则的校验不够完善,比如 2 月份只有 28 天的情况,或者 29 天的情况。这里没有做到控制。更完善的校验需要编写一个方法来实现。

邮箱

邮箱的校验分为以下几个部分:

① 只允许英文字母、数字、下划线、英文句号、以及中划线;([a-zA-Z0-9._-])+

②@符号;@

③ 域名:一般域名的规律为“[N 级域名.][三级域名.]二级域名.顶级域名”,比如“ qq.com ”、“ www.qq.com ”、“ mp.weixin.qq.com ”、“ 12-34.com.cn ”,分析可得域名类似“ ** .** .** .** ”组成。

1
`**` 可表示为:([a-zA-Z0-9_-])+
1
`.**` 可表示为:(.[a-zA-Z0-9_-]{2,3})
1
`**.**.**.**` 得到:([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3})){1,3}

④ 讲上述上个结合得到:

1
2
3
/^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3})){1,3}$/
// 根据特殊字符 \w 相当于 `[A-Za-z0-9_]`。于是可以用以下正则代替上行
/^[\w.-]+@[\w-]+(.[\w-]{2,3}){1,3}$/

强密码(必须包含大小写字母和数字的组合,长度在 8-16 之间)

强密码校验分为以下几个部分:

① 长度 8-16 位{8,16}

② 包含大小写字母和数字[a-zA-Z0-9]{8,16}

③ 确保同时含有字母和数字?

这里使用(?=.*\d)(?=.*[a-z])(?=.*[A-Z]) 来匹配当前式子同时含有大小写字母和数字。其中 (?=) 是用来预测后续的内容与当前表达式匹配。参见第三点的量词类倒数第二个。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。这里使用了三个预测先行(?=)(?=)(?=)也就是说需要同时满足三个匹配条件。

④ 最终得出结果:

1
/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,16}/

更多内容待续……