写在前面

正则真是个伟大的发明啊。分分钟提高工作效率,
以前删除某个文件夹下面的文件(Mac):

command + A  && command + delete

现在只需在命令行下

rm -rf *

而且如果你要删除的文件有规律的话,

// 删除开头为'2017-11-'的所有文件
rm -rf 2017-11-*
// 删除.txt文件 
rm -rf *.txt

简直是进入现代化啊。总而言之,学好正则非常必要啊。
本文的代码使用JavaScript书写。javascript 对正则的实现基于RegExp对象。其说明文档在(MDN-RegExp介绍),可以了解下。

一、几个概念

正则表达式

正则表达式是描述一组字符串特征的模式,用来匹配特定的字符串。——Ken Thompson

字符串字面值 原生的字符串,没有添加正则元素在里面,看到什么就是什么。比如Hello world 这个就是一个字面值。

元字符 在正则表达式中有特殊含义的字符,是正则表达式保留字。比如*+?[]

字符组 用于匹配字符的集合,通常置于[]内,如[0-9][a-z]

字符组简写式
如其名字所说,是字符组的简写形式。如\d匹配数字,相当于[0-9],使用简写式可以使表达式更精炼。

捕获分组vs非捕获分组 正则表达式中通常用括号(分组内容)来表示一个捕获分组,以便后续对其引用,它通常和 后向引用 相联系。与之相对的是非捕获分组(?:分组内容) 。因为非捕获分组不会存储到内存中,通常性能会好于捕获分组。如:(abc)#\1可以匹配abc#abc,这里\1引用了前面的(abc),非捕获分组表示abc 则可以写成(?:abc)

量词 量词用于描述某个模式出现的个数。

* 用于表示0个或多个
?表示0个或1个
+ 表示1个或多个
{n} 表示出现n个

边界 用来标记字符串中的位置,如^
$ 分别用于匹配行的起始和结束位置。\b用于标记单词的边界.

二、简单的模式匹配

2.1 匹配字符串字面量
var hw = /hello world/;
hw.test('hello world');// true
2.2 匹配数字和非数字

对于单个数字,我们可以用[0-9],也可以用\d,当然也可以用[0123456789],根据具体需要我们也可以选择部分数字进行匹配[12],这只会匹配1和2。

// 匹配0-9的数字
var reg1 = /[0-9]/;
// 简写形式
var reg2 = /\d/;

reg1.test('5');
reg2.test('5');

举个例子,我们可以用数字匹配来验证年份。

// 匹配1000 ~ 2999
var yearReg = /^[1-2]\d\d\d$/;
yearReg.test('1970');
yearReg.test('2999');

\d相反的是\D用于匹配非数字字符,它相当于[^\d]

2.3 匹配单词和非单词字符

\w 用于匹配单词字符,何谓单词字符,其实就相当于[_a-zA-Z0-9],既数字、字母、和下划线。
同样它的相反是\W,大写的W

2.4 匹配空白符

\s用于匹配空白符,它相当于[ \t\n\r],既空格、制表符(\t)、换行符(\n)、回车符(\r)。
这个应用就挺大了,比如利用replace()可以把文本中的空白符去掉。

var sReg = /\s/;
var text = 'wor ld';
// 删除空白字符
text.replace(sReg, '');//world
2.5 匹配任意字符

.用于匹配任意字符。结合量词我们可以用来匹配字符长度。

var reg = /^.{4}$/;
reg.test('-R3s');
reg.test('hello');

三、选择、分组和引用

3.1 选择

选择操作可以在多个子模式中选择一种,(html|HTML)可以匹配html也可以匹配HTML,

var reg = /<(html|HTML)>/;
reg.test('<html>');//true
reg.test('<HTML>');//true
3.2 捕获分组和后向引用

前面提到过,()表示一个捕获分组,括号代表一个分组的开始,从左到右分别1、2、3……,引用的时候就可以用\1\2来引用了。

// 这里\1表示前面的(html|HTML)
var reg = /<(html|HTML)>.*<\/\1>/;
reg.test('<html><body></body></html>');//true
reg.test('<HTML><body></body></HTML>');//true
3.3 非捕获分组

有时候我们的分组并不需要后面引用,这时候可以使用非捕获分组来提升性能。


// 判断广东省广州市的电话号码
var reg = /^(?:020)-\d{8}$/;
reg.test('020-88886666');//true

// 判断151或127开头的手机号
var reg2 = /^(?:151|127)\d{8}$/;
reg2.test('15166668888');//true

四、匹配Unicode字符

\uXXXX 或者\xxx用于匹配Unicode 字符,
"京"的Unicode编码为\u4eac
那么我们可以尝试匹配一下北京的车牌号:

var reg = /^\u4eac[A-Z][0-9_A-Z]{5}$/;
reg.test('京AF2345');//true

五、结语

正则表达式是相当强大的工具,这篇文章只能算是自己入门的一个简单的总结。还有许多特性等待在实践中发掘。


will233
538 声望3 粉丝

天下大事,必作于细。