一、什么是正则表达式
正则表达式的概念:
计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本
在JS中,正则表达式属于对象的一种:
typeof /\d+/
"object"
Object.prototype.toString.call(/\d+/);
//"[object RegExp]"
正则对象有两个常用属性:
- flags:该正则对象的标志
- lastIndex:下一次开始匹配的起点
二、如何使用正则表达式
0. 如何创建一个正则表达式
创建正则表达式有两种方法,一种是将正则表达式内容直接写在//之中,另一种是通过构造函数创建对象,两种方法等效。
var reg1=/\d+/;
//直接创建
var reg2=new RegExp(/\d+/);
//通过构造函数创建正则对象
var reg3=new RegExp("\\d+")
//通过构造函数创建正则对象时,也可以传入一个字符串作为参数,此时应省去双斜线,
//且内部的符号要进行转义
1. 一个正则表达式的构成
先来看一个最基础的例子:
var re=/hello\w+\-?\d*/i;
var password=/[a-zA-Z\_\$][0-9a-zA-Z\_\$]*/;
通过这两个表达式来看,正则表达式主要分为几个部分:
①.要匹配的内容
正则表达式中表示要匹配的内容有以下几种方法:
- 直接给出字符:如上文的hello,就会匹配字符串"hello"
- 使用占位符:占位符可以用来匹配一类字符,如文中的\w表示匹配字母或数字
- 对于特殊字符,使用转义的方式:如上文中匹配-符号时,用\-的方式
- 使用[]进行范围匹配:如上文的password,匹配的是JS允许的变量名,[a-zA-Z\_\$]表示大小写字母或_或$这个范围中的任意字符,后一个括号内同理
- 使用(a|b),表示匹配a或b,这里的a和b不一定是一个字符,也可能是其他几种内容
其中占位符又分以下几种:
- \d匹配数字
- \w匹配字母或数字
- \s匹配空白符,空格或tab等
- .匹配任意字符(回车换行符除外)
②.要匹配内容的数量
这里的数量是指,我要匹配多少个字符,比如\w+表示至少一个字母或数字,\-?表示0或1个-符号
表示数量有以下几种方法:
- * 表示任意个
- + 至少一个
- ? 0个或1个
- {n}n个
- {n,m}n到m个
要注意一下,这里说的数量,只限制紧挨着数量标记的那一个字符,如/23+/表示匹配一个2,至少一个3。如果我们要匹配任意个23的话,就要引入子表达式的概念:即把正则表达式的一部分用小括号括起来,此时它后面跟着的数量限制就会作用于这整个子表达式。如/(23)+/匹配的就是23232323这样至少一个23,而不再是一个2多个3了
③.正则表达式的标志
正则表达式的标志在双斜线//之外,用于进一步精确正则表达式的行为,如上文中的i
标志主要有以下几种:
- i:忽略大小写
- g:全局搜索,每次使用exec后会更新正则对象的lastIndex属性;使用字符串的match方法时可以进行多次匹配
- y:粘连搜索,即下一次执行exec匹配时必须从上一次结束之后紧接着的位置开始
- m:执行多行匹配
- u:将可以识别码点大于0xFFFF的字符
- s :dotAll模式,此时.可以匹配回车换行符,真正做到匹配任意字符
var reg=/\d{1}/;
var regG=/\d{1}/g;
var regY=/\d{1}/y;
var str="0hello1world2";
reg.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
reg.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
//每次都是从开头进行一次匹配
regG.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
regG.exec(str)
//["1", index: 6, input: "0hello1world2", groups: undefined]
regG.exec(str)
//["2", index: 12, input: "0hello1world2", groups: undefined]
regG.exec(str)
//null,因为已经搜索到了末尾
//如果再次进行搜索会再次从头开始:
regG.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
regY.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
regY.exec(str)
//null,因为上次搜索到0之后,紧跟着的是h,不符合要求
//再次执行则会从头再开始:
regY.exec(str)
//["0", index: 0, input: "0hello1world2", groups: undefined]
2. 使用方法
从上面的例子中也已经看出来了,使用正则表达式匹配字符串最基本的方法就是正则对象的exec方法:
该方法返回一个数组,数组的第一个元素是与正则表达式匹配的文本,后面的元素依次是与正则表达式若干个子表达式相匹配的文本(如果有的话)。若匹配失败,则返回null
exec方法返回的数组除了length还有两个属性:
- index:表示匹配的文本的第一个字符的位置
- input:存放被检索的字符串
除了用exec方法,我们还可以使用String对象的match方法,它的使用方法和exec类似
var str="0hello1";
str.match(/\d+/);
//["0", index: 0, input: "0hello1", groups: undefined]
str.match(/\d+/g);
//["0", "1"]
要注意二者的区别,在执行全局搜索时,match方法会返回一个数组,里面是所有匹配成功的字符,而这个数组没有index和input属性。当不进行全局搜索时,二者可以认为是等价的
此外,正则表达式还可以使用test方法来检测一个字符串是否符合要求,该方法返回一个布尔值
var reg=/hello\d+/;
reg.test("hello1")//true
reg.test("hello JS")//false
3. 进阶使用方法
对字符串的起始结束字符进行约束
很多场景下,我们要控制字符串的开头或结尾,如不能使用数字开头,或要以某一字符结尾。
- ^表示行的开头
- $表示行的结尾
断言匹配
对字符位置进一步限制:
- 先行断言:只有x在y前面才匹配,写做/x(?=y)/
- 先行否定断言:只有x不在y前面才匹配,写做/x(?!y)/
- 后行断言:只有x在y后面才匹配,写做/(?<=y)x/
- 后行否定断言:只有x不在y后面才匹配,/(?<!=y)x/
组匹配和具名组匹配
普通的组匹配,即使用子表达式,将字符串中不同的部分提取到数组中
具名组匹配:给每个子表达式取一个名字,在该正则表达式中可以再次使用这个子表达式。
var reg=/(?<word>[a-z]+)\_\k<word>/;
reg.test("hello_js")//true
上面的代码中,首先定义了一个具名子表达式word,匹配小写字母,在后面再次使用了这个子表达式,整个正则表达式用来匹配用下划线连接的两个小写单词
三、使用正则表达式能干什么
0. 判断特定字符串
要检验某一字符串是否符合特定的格式,最方便的方式就是正则表达式:
//判断变量是否符合命名规则,v是要进行判断的变量名
var value=/[a-zA-Z\_\$][0-9a-zA-Z\_\$]*/;
value.test(v)
1. 切割字符串
在读取用户的输入的多个数据时,数据间的分隔符可能是多种多样的,有的人用一个空格,有的人用多个空格,有的人用逗号顿号句号分号,而我们读取的是一整个的字符串,如何把这个字符串拆分为一个个数据项呢,此时正则就可以上场了
var reeg=/[\s\,\、\。\,]+/
var data=dataInput.split(reg);
这样写,程序的容错率就会明显得到提高
2.提取字符串信息
上面已经提到过,使用exec方法或是String对象的match方法,可以得到一个数组,里面存放字符串中与正则表达式中匹配的内容,因此使用该方法我们就可以便捷的提取字符串中的信息。
要注意的是,正则匹配默认是贪婪匹配,即尽可能匹配多的字符
var re = /^(\d+)(0*)$/;
re.exec('102300'); // ['102300', '102300', '']
var reg=/^(\d+?)(0*)$/;
reg.exec('102300'); // ['102300','1023','00']
3.替换字符串
使用string对象的replace方法可以对字符串中的某一部分进行替换,使用正则字符串后,可以方便的选中字符串中的特定字符,如显示客户信息时要将字符串中的金额数字替换为X
str.replace(/\d+/,"X");