浅谈正则

强大且高效的字符串模式

2018-08-10
本文约1.5k字

作为一枚程序猿,无论是前端还是后端,对正则都不会陌生。正则表达式对于处理字符串、对字符串制定验证规则有着强大而高效的能力。

什么是正则表达式?

正则表达式是使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。它可以针对特定要求完成我们对字符串的处理要求,在程序世界里使用广泛。特别是在表单输入验证的环节,正则表达式起到了举重若轻的作用。例如我们想要验证用户是否输入了一组6位数字就可以使用这样的规则:

1
/^[0-9]{6}$/

这个例子只是简单让你知道正则表达式可以做什么,我们接下来从基础开始说起。

正则表达式对象及修饰符

正则表达式对象有两种定义方式
1、构造函数定义
通过new RegExp(pattern, attributes)的方式构造,如:

1
var reg = new RegExp("abc","g")

其中pattern为表示表达式内容,上面的例子表示匹配abc.
attributes表示:

g 全局匹配
i 不区分大小写
m 多行匹配

2、文本定义
/pattern/attributes,如:

1
var reg = /abc/g;

等价于第一种构造函数方式

元字符

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,'n'匹配字符n'\n'匹配一个换行符。序列'\\'匹配 \,而'\('则匹配(
+ 匹配一次或多次
* 匹配0次、1次或多次
? 匹配0次或1次
. 匹配除换行符之外的任何字符
{n} n为非负整数,匹配n次
{n,} 至少匹配n次
{n,m} 匹配n~m次
^ 匹配字符串开始,值得注意的是它还有另外一个含义。当在一组方括号里使用^时,它表示排除的意思,常常用来剔除某个字符
$ 匹配字符串结束
(?=pattern) 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串
(?!pattern) 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串
x|y 匹配x或y
[xyz] 匹配xyz中的任一个字符
[^xyx] 匹配除xyz的任一个字符
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,"er\b"可以匹配"never"中的er,但不能匹配"verb"中的er
\B 匹配非单词边界
\d 匹配一个数字,相当于[0-9]
\D 匹配非数字字符,相当于[^0-9]
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[\f\n\r\t\v]
\S 匹配任何非空白字符。等价于[^\f\n\r\t\v]
\w 匹配字母、数字、下划线。等价于[A-Za-z0-9_]
\W 匹配非字母、数字、下划线。等价于[^A-Za-z0-9_]

非贪婪模式

*+限定符都是贪婪的,他们会尽可能的多匹配字符,在其后面加上?便可以实现最小匹配。
如对于字符串starstarstar,s.\*r匹配的是starstarstar,而s.\*?r匹配的是star

正则相关方法

test()

test()是正则表达式方法,用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回true,否则返回false

1
2
// reg为正则规则,str为待测试字符串
reg.test(str)

exec()

exec()是正则表达式方法,用于检索字符串中的正则表达式的匹配,该函数返回一个数组,存放匹配的结果。如果未找到匹配,则返回值为null。但若有匹配的情况下,exec()返回的数组长度永远为1。exec()方法受参数g影响,如果不指定g那么它永远返回第一个匹配值,如果指定了g那么下一次调用时它将从上一次结束的位置继续查找,下面这个例子可以很清楚的向你解释这一点:

1
2
3
4
var str = "star1star2star3"; 
var reg = new RegExp("star.", "g");
console.log(reg.exec(str)[0]); // star1
console.log(reg.exec(str)[0]); // star2

match()

以下方法皆为字符串方法。
match()有点类似于exec()的作用,只不过当指定了g时,match()方法一次性返回所有匹配结果。

1
2
3
var str = "star1star2star3"; 
var reg = new RegExp("star.", "g");
console.log(str.exec(reg)); // ["star1","star2","star3"]

search()方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置,若无结果则返回-1

split()

split()根据正则规则分割字符串返回数组

replace()

replace()方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
$1,…$9: 正则表达式中有几个(),就会传递几个参数,$1~$9分别代表本次匹配中每个()提取的结果,最多9个
例如:

1
mobile.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2")

这是一个手机号加密的正则

常用正则

1
2
3
4
5
6
// 手机号码
/^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/
// 固定电话
/^(400|800)([0-9]{7})|(0\d{2,3}(-?)\d{7,8})$/
// 金额千分位
str.replace(/\B(?=(\d{3})+(?!\d))/g, ',')

可视化在线校验工具

https://www.debuggex.com/
很棒的在线工具,不仅可以帮你运算出结果,还可以让你结合图形一环一环的捋清验证的过程,方便你进行修改调试
reg