正则表达式

概述

正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。比如,正则表达式给出一个 Email 地址的模式,然后用它来确定一个字符串是否为 Email 地址。JavaScript 的正则表达式体系是参照 Perl 5 建立的。

新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。

1
var regex = /xyz/;

另一种是使用RegExp构造函数。

1
var regex = new RegExp('xyz');

上面两种写法是等价的,都新建了一个内容为xyz的正则表达式对象。它们的主要区别是,第一种方法在引擎编译代码时,就会新建正则表达式,第二种方法在运行时新建正则表达式,所以前者的效率较高。而且,前者比较便利和直观,所以实际应用中,基本上都采用字面量定义正则表达式。

RegExp构造函数还可以接受第二个参数,表示修饰符(详细解释见下文)。

1
2
3
4
var regex = new RegExp('xyz', 'i');

// 等价于
var regex = /xyz/i;

上面代码中,正则表达式/xyz/有一个修饰符i。

修饰符

g修饰符

默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。

i修饰符

默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignorecase)。

元字符

元字符 描述
\d 查找数字 [0-9]
\D 非数字字符 [^0-9]
\w 单词字符 [a-zA-Z0-9_]
\W 非单词字符 [^a-zA-Z0-9_]
\s 不可见字符,包含空格 [\f\r\n\t\v]
\S 非不可见字符 [\f\r\n\t\v]
\t 查找制表符
. 除了换行和回车之外的任一字符 [^\n\r]

运算符

运算符 描述
() 提升优先级,优先级最高 ,一个 () 表示一个组匹配
[] 表示一个字符的位置,[] 中定义需要匹配的字符
^ [] 中表示非 , // 中表示匹配开始位置
{} 定义量词,表示某字符出现的次数

| 表示或者,优先级最低。

注:1.[] 中,特殊字符不需要使用 \ 进行转义处理,但是如果需要使用 [] 匹配 \ 自身的话,那么就需要转义。
2. 对于字符 - 来说,如果是放在数字或字母之间,则表示匹配这一段范围的字符,否则就是匹配 - 自身。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 匹配 \
(/[\\]/.test('\\'))
// true

// 匹配其他特殊字符
(/[+]/.test('+'))
// true

// 匹配 -
(/[-]/.test('-'))
// true

// 匹配 0-9 a-z
(/[0-9a-z]/.test('5'))
// true

量词

格式 描述
x{n,m} 表示 x 出现 n 至 m 次 , x>=n && x<=m
x{n,} x 出现 n 个以上 ,x>=n
x{n} x 出现 n 个 ,x==n
x+ x 出现 1个 或 1个 以上,x>=1
x* x 出现 0个 或 0个 以上,x>=0
x? x 出现 0个 或 1个,x==0 或 x==1
^x 以x开始
x$ 以x结尾

转义符

如果需要匹配特殊字符(比如:RegExp 中使用到的特殊字符)。那么,我们需要对这些字符使用 \ 进行转义。

需要转义的特殊字符有:

  • \
  • /
  • +
  • -
  • *
  • .
  • {
  • }
  • ^
  • $
  • (
  • )
  • [
  • ]

例如,匹配 / 字符时,我们需要转义。

1
2
(/\//.test('/'))
// true

注意:

如果是以 new RegExp() 构造函数的方式定义正则表达式,由于其中的参数是字符串类型,所以在转义的时候需要使用两个 \\ 进行转义。

1
2
(new RegExp('\\/').test('/'))
// true

特殊的:

在对 \ 进行匹配时,需要进行特殊处理,原因是 \ 本身就是转义符。以下分别是以字面量方式和构造函数定义正则时的写法。

1
2
3
4
5
6
7
//1. 字面量
(/\\/.test('\\'))
// true

//2. 构造函数
(new RegExp('\\\\').test('\\'))
// true

注:传入的 \\ 测试字符加入了 2 个,是因为 javascript 引擎会认为需要将右边的引号 ' 转义,所以加一个 \

RegExp实例方法

RegExp.prototype.test()

检索字符串是否满足正则表达式的要求。

参数:string类型,需要检测的字符串

返回值:boolean 类型 ,true 表示匹配满足正则表达式要求,false 表示不满足要求

RegExp.prototype.exec()

正则实例对象的exec方法,用来返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null

1
2
3
4
5
6
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

上面代码中,正则对象r1匹配成功,返回一个数组,成员是匹配结果;正则对象r2匹配失败,返回null

如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length属性等于组匹配的数量再加1。

1
2
3
4
var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]

上面代码的exec方法,返回一个数组。第一个成员是整个匹配的结果,第二个成员是圆括号匹配的结果。

exec方法的返回数组还包含以下两个属性:

  1. input:整个原字符串。
  2. index:整个模式匹配成功的开始位置(从0开始计数)。
1
2
3
4
5
6
7
var r = /a(b+)a/;
var arr = r.exec('_abbba_aba_');

arr // ["abbba", "bbb"]

arr.index // 1
arr.input // "_abbba_aba_"

上面代码中的index属性等于1,是因为从原字符串的第二个位置开始匹配成功。

如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var reg = /a/g;
var str = 'abc_abc_abc'

var r1 = reg.exec(str);
r1 // ["a"]
r1.index // 0
reg.lastIndex // 1

var r2 = reg.exec(str);
r2 // ["a"]
r2.index // 4
reg.lastIndex // 5

var r3 = reg.exec(str);
r3 // ["a"]
r3.index // 8
reg.lastIndex // 9

var r4 = reg.exec(str);
r4 // null
reg.lastIndex // 0

上面代码连续用了四次exec方法,前三次都是从上一次匹配结束的位置向后匹配。当第三次匹配结束以后,整个字符串已经到达尾部,匹配结果返回null,正则实例对象的lastIndex属性也重置为0,意味着第四次匹配将从头开始。

利用g修饰符允许多次匹配的特点,可以用一个循环完成全部匹配。

1
2
3
4
5
6
7
8
9
10
11
var reg = /a/g;
var str = 'abc_abc_abc'

while(true) {
var match = reg.exec(str);
if (!match) break;
console.log('#' + match.index + ':' + match[0]);
}
// #0:a
// #4:a
// #8:a

上面代码中,只要exec方法不返回null,就会一直循环下去,每次输出匹配的位置和匹配的文本。

正则实例对象的lastIndex属性不仅可读,还可写。设置了g修饰符的时候,只要手动设置了lastIndex的值,就会从指定位置开始匹配。

常见验证

邮箱

前面是字母或者数字
必须有@
@后面是字母或者数字
必须有.
.后面是字母或者数字

1
2
var r = /^\w+@\w+(\.\w+)+$/;

手机号

11位数字组成
号段13[0-9] 147 15[0-9] 177[0178] 18[0-9]

1
2
3

var r = /^(13[0-9]|147|15[0-9]|17[0178]|18[0-9])\d{8}$/;

中文名

只能是汉字
长度2-6位之间
汉字范围[\u4e00-\u9fa5]

1
var r = /^[\u4e00-\u9fa5]{2,6}$/;

小数位数

只能是数字
小数位数不得超过 2 位

1
var r = /^\d+(.\d{1,2})?$/

金额验证

十进制位及以上不能为 0
最多保留2位小数
必需为数值
可以为空

1
var r = new RegExp("^(((^[1-9]\\d*)|(^[0-9]))+(\\.\\d{1,2})?)?$")