正则表达式

正则表达式常用于对字符串匹配及检索替换,是操作字符串文本最强大的工具。

它有两种写法如下,作用是一样的。

// 构造函数
var patt = new RegExp(pattern, modifiers);
// 自面量
var patt = /pattern/modifiers;

代码中,modifiers 表示修饰符,意思是使用何种方式匹配文本,有三个选项:

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

pattern 则是表达式的模式,由各种各样的简单符号组成,逻辑上讲可以匹配任何文本。下面我们介绍这些符号以及具体的含义是什么。

元字符

字符由普通字符和元字符组成,普通字符就是 abc123,元字符则是拥有特殊含义的字符,大部分是\加一个字母的形式,表示某一类字符串。

  • .:表示单个字符,除了换行符(\n)。
  • \w:表示单词字符(word),即数字、字母、下划线。
  • \W:表示非单词字符,\w 取反。
  • \d:表示单个数字(digit)。
  • \D:表示非数字,\d 取反。
  • \s:表示空白字符(space)。
  • \S:表示非空白字符。
  • \b:表示单词边界(border),即一个英文单词的开头或结尾。
  • \B:表示非单词边界。
  • \n:表示换行符(newline)。
  • \r:表示回车符(return)。

注意:上述元字符仅匹配一个字符,匹配多个需要量词来控制。

量词

量词是对字符数量控制的另一种特殊字符。下面用 n 表示一个字符,X,Y表示数量,看一下量词的用法:

  • n+:至少一个,即 >= 1。
  • n*:0 或多个,即 >= 0;0 表示不存在。
  • n?:0 或一个,即 == 0 | == 1。
  • n{X}:固定 X 个,即 == X。
  • n{X,}:至少 X 个,即 >= X。
  • n{X,Y}:至少 X 个,即 >= X & <= Y。

还有几个通过位置来过滤字符的量词,如下:

  • n$:匹配 n,条件是最后一个。
  • ^n:匹配 n,条件是第一个。
  • ?=n:匹配某个字符,条件是后面紧跟着 n;需要用括号包裹,如:m(?=n)。
  • ?!n:匹配某个字符,条件是后面没有紧跟着 n;需要用括号包裹。

注意:量词会优先匹配尽可能多的字符,比如:

var str = 'aabbbcc';
str.match(/b+/); // bbb
// 优先匹配3个b而不是1个b

括号

普通字符(abc)和元字符(\n\f)都表示一个固定的值。如果我们需要动态匹配一个值,比如 d,e,f 三个值中的任意一个值,那么就需要方括号。

  • [abc]:括号之内的一个字符。
  • [^abc]:括号之外的字符,[abc]取反。
  • [0-9]:从 0 至 9 的数字。
  • [a-z]:从 a 到 z 的字母(小写)。
  • [A-Z]:从 A 到 Z 的字母(大写)。
  • [A-z]:从 A 到 z 的字母(大小写)。

量词只能匹配一个字符,很多情况下需要匹配一组字符,就要用到大括号了。大括号 + 量词可以对一组连续的值匹配。

  • (abc):abc 为一组值。
  • (abc|bcd):abc 或 bcd 任意一组值。

注意:方括号之内使用量词、大括号都无意义。因为量词尽可能匹配多个,而方括号只匹配一个,如下:

var str = '00100110';
// 以下三种匹配结果一样
strs.match(/[(01)]/g);
strs.match(/[0*1+]/g);
strs.match(/[01]/g);

所以方括号内只写值即可,不需要嵌套其他的符号。

函数

正则表达式匹配内容,需要通过一些函数来匹配字符串与表达式:

1. 正则函数

  • test(string):验证参数是否与正则匹配,返回 Boolean 值。
  • exec(string):找到一个正则的匹配,返回 String 或 Null 值。

2. 字符串函数

  • match(regexp):找到一个或多个正则匹配的字符,返回 Array。
  • replace(regexp):替换字符串中正则匹配到的内容。
  • search(regexp):搜索字符串中匹配正则的字符,返回索引。
  • split(regexp):以正则匹配到的字符分割字符串,返回 Array。

实践

正则表达式由 “字符 + 量词 + 修饰符” 组成,学完了上面的基础知识,我们现在可以尝试实践了。

1. 匹配手机号

var patt = /1[3456789]\d{9}/;

上述表达式,我们共匹配了 18 位字符,并控制了第 1 位和第 2 位的值。那么是否匹配成功呢,使用正则的 .test() 方法来验证一下:

patt.test('17066669999'); // true
patt.test('12066669999'); // false
patt.test('08817066669999000'); // false

正则是从左向右匹配的,如果要严格控制字符数量,就要添加首尾标记符,修改如下:

var patt = /^1[3456789]\d{9}$/;

2. 匹配身份证号:

var patt = /^\d{17}[\dX]$/;