JavaScript(八)-正则表达式

正则表达式是用于匹配字符串中字符组合的模式。

创建正则表达式

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

一种是使用字面量,以斜杠表示开始和结束。

1
var regex = /xyz/;

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

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

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


修饰符

g:表示全局(global)模式,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。

i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写。

m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在于模式匹配的项。

匹配规则

元字符

正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符。正则表达式中的元字符包括:

( [ { \ ^ $ | ? * + . } ] )

不是每个元字符都有特定的意义,在不同的组合中元字符有不同的意义

字符 含义
\t 水平制表符
\r 回车符
\n 换行符
\f 换页符
\v 垂直制表符
\0 空字符

字符类

字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内,比如[xyz] 表示xyz之中任选一个匹配。

例如:匹配一个数字(或大小写字母)

1
var reg =/[0-A9-c5-Bn-Z]/ig

预定义模式

预定义模式指的是某些常见模式的简写方式。

字符 等价类 含义
. [^\r\n] 除了回车符和换行符之外的所有字符
\d [0-9] 数字字符
\D [^0-9] 非数字字符
\s [ \t\r\n\v\f] 空白符
\S [^ \t\r\n\v\f] 非空白符
\w [a-zA-Z_0-9] 单词字符,字母、数字下划线
\W [^a-zA-Z_0-9] 非单词字符

如我们希望匹配一个可以是ab+数字+任意字符的字符串,就可以这样写了/ab\d./

1
var reg = /ab\d./

边界

正则表达式还提供了几个常用的边界匹配字符

字符 含义
^ 以xxx开头
$ 以xxx结尾
\b 单词边界
\B 非单词边界

例如:

1
2
3
4
5
6
7
var str = 'hello1 world hello2 123456 \t \r jirengu \n tennant hello3'
str.match(/hello\d/g) // ["hello1", "hello2", "hello3"]
str.match(/^hello\d/g) // ["hello1"]
str.match(/hello\d$/g) // ["hello3"]

var str2 = 'hello1 whello9orld hello2 12-hello8-3456 \t \r jirengu \n tennant hello3'
str2.match(/\bhello\d\b/g) //["hello1", "hello2", "hello8", "hello3"]

量词匹配

字符 含义
? 出现零次或一次(最多出现一次)
+ 出现一次或多次(至少出现一次)
* 出现零次或多次(任意次)
{n} 出现n次
{n,m} 出现n到m次
{n,} 至少出现n次

贪婪模式与非贪婪模式

贪婪模式:
默认情况下,? + * {min, max}都是贪婪的,也就是说,它会根据前导字符去匹配尽可能多的内容。

非贪婪模式:
非贪婪就是匹配尽可能少的内容。也就是说一旦成功匹配不再继续尝试,做法很简单,在量词后加上?即可。


点击查看更全面的特殊字符描述


实例属性

正则对象的每个实例都具有下列属性:

ignoreCase:返回一个布尔值,表示是否设置了i修饰符。

global:返回一个布尔值,表示是否设置了g修饰符。

multiline:返回一个布尔值,表示是否设置了m修饰符。

lastIndex:返回一个数值,表示下一次开始搜索的位置,从0算起。

source:返回正则表达式的字符串形式(不包括反斜杠)。

1
2
3
4
5
6
7
var r = /abc/igm;

r.ignoreCase // true
r.global // true
r.multiline // true
r.lastIndex // 0
r.source // "abc"

实例方法

RegExp.prototype.test()

方法用于测试字符串参数中是否存正则表达式模式,如果存在则返回true,否则返回false

1
2
3
4
5
6
7
var reg = /\d+\.\d{1,2}$/g;

reg.test('123.45'); //true
reg.test('0.2'); //true

reg.test('a.34'); //false
reg.test('34.5678'); //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

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

  1. input:整个原字符串。

  2. index:整个模式匹配成功的开始位置(从0开始计数)。

String.prototype.match()

字符串实例对象的match方法对字符串进行正则匹配,返回匹配结果。

字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1

String.prototype.replace()

字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。

1
str.replace(search, replacement)

正则表达式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。

1
2
3
'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"

上面代码中,最后一个正则表达式使用了g修饰符,导致所有的b都被替换掉了。

实用示例

  1. 判断用户输入的是不是合法的用户名(长度6-20个字符,只能包括字母、数字、下划线)。
1
2
3
4
5
6
7
function isValidUsername(str){
if(/^\w{6,20}$/.test(str)){
console.log("是合法的用户名")
}else{
console.log("不是合法的用户名")
}
}
  1. 判断用户输入的是不是手机号。
1
2
3
function isPhoneNum(str){
return /^1[3-8]\d{9}$/.test(str)
}
  1. 判断用户输入的是不是邮箱。
1
2
3
4
5
6
7
8
9
10
11
function isEmail(str){
return /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(str)
}
解释:
1. 以大写字母[A-Z]、小写字母[a-z]、数字[0-9]、下滑线[_]、减号[-]及点号[.]开头,并需要重复一次至多次[+]。

2. 中间必须包括@符号。

3. @之后需要连接大写字母[A-Z]、小写字母[a-z]、数字[0-9]、下滑线[_]、减号[-]及点号[.],并需要重复一次至多次[+]。

4. 结尾必须是点号[.]连接24位的大小写字母[A-Za-z]{2,4}。
  1. 去除字符串两边的空白字符。
1
2
3
function trim(str){
return str.replace(/^\s+|\s+$/g,'');
}

资源

一个可以用图示表达正则的网站:regexper