修饰符
正则表达式的修饰符是用以说明高级匹配模式的规则,并且修饰符是放在//
双斜杠外面的,例如这样 /java/g
,g就是修饰符
接下来给出一张表,列出了修饰符的种类和含义
字符 |
含义 |
i |
执行不区分大小写的匹配 |
g |
执行全局匹配,即找到所有匹配的项并返回,而不是找到第一个之后就停止 |
m |
多行匹配模式 |
我们来逐个讲解它们各自的用途:
- 字符 i
我们之前会用这样的匹配模式去匹配 /[Jj]ava[Ss]cript/
,这是因为我们不知道字符串中写的是 javascript
还是 JavaScript
。其实我们可以直接用一个修饰符 i 来避免大小写的干扰,就想这样 /javascript/i
let pattern = /javascript/ilet str = "JavaScript" str.match(pattern) // 返回 ['JavaScript'] 匹配成功
我们可以看到,匹配时忽略了大小写的影响,仍然匹配成功了
- 字符 g
我们之前匹配字符串时,都是匹配到第一个就结束匹配返回内容,例如
let pattern = /java/let str = "I love javascript and java" str.match(pattern) //返回 ["java"] 匹配到javascript的java就返回了
我们可以看到 str 字符串中,有两个java,但只匹配到javascript就返回了,如果我们要匹配到字符串中所有符合匹配模式的字符串,我们就可以用修饰符g,就像这样 /java/g
let pattern = /java/glet str = "I love javascript and java" str.match(pattern) //返回 ["java", "java"] 匹配到了所有的java
- 字符 m
如果一个字符串中包含换行符,则该字符串就有多行。这时我们可以使用修饰符 m 进行多行模式的匹配。
let pattern = /java$/mlet str = "java\nis fun" str.match(pattern) //返回 ['java'] 匹配成功
在这个例子中,str内有一个换行符,这样的话,第一行就是 java
,第二行就是 is fun
。我们的匹配模式是查找每一行,只要这一行的结尾是java,就返回匹配到的内容。
其实在这个例子中,我们看到,使用了修饰符 m 以后,锚字符 ^ 和 $ 不再是以一整个字符串的开头或结尾为匹配点了,而是以每一行的开头或结尾为匹配点。
用于模式匹配字符串的方法
我们在前面的很多例子中用到了search()
方法 、match()
方法,他们都是匹配字符串的方法,其实还有很多种匹配的方法,他们的用法和作用各不相同,我们来了解一下
用于模式匹配字符串的方法有以下几种:
- search( )
- replace( )
- match( )
- split()
接下来我们来详细讲解一下
- search()
该方法需要传入一个正则表达式作为参数,并返回第一个与之匹配的字符串的起始位置,若没匹配到,则返回-1
"javascript".search(/script/) //返回 4 "javascript".search(/sccc/) //返回-1
- replace()
该方法是用于字符串的检索与替换。需要传入两个参数,第一个参数为正则表达式;第二个参数为需要进行替换的字符串。匹配成功则会用第二个参数去替换匹配到的字符串,并返回替换后的整体字符串;若没匹配成功,则返回原来的整体字符串。
"javascript".replace(/java/, 'python') //返回 pythonscript "javascript".replace(/abc/, 'python') //返回 javascript
若使用了修饰符g,则会将所有匹配到的字符串都进行一个替换。
"javascript and java".replace(/java/, 'python') //返回 pythonscript and java"javascript".replace(/java/g, 'python') //返回 pythonscript and python
- match()
该方法需要传入一个正则表达式作为参数,返回一个由匹配结果组成的数组,如果正则表达式使用了修饰符g,则将所有匹配到的结果都放到数组中并返回。
"javascript and java".match(/java/) //返回 ['java'] "javascript and java".match(/java/g) //返回 ['java', 'java']
补充:当match()传入一个非全局的正则表达式时,实际上返回的数组里有两个属性:index和input,他们分别表示匹配到的字符串的起始位置和检索的整个字符串。
let ret = "I love javascript and java".match(/java/)ret.index //返回 7ret.input //返回 I love javascript and java
- split()
该方法是用于将字符串分割,并将分割开的部分作为数组中的元素,最终返回一个数组。该方法需要传入一个正则表达式作为参数,去确定需要根据什么去分割这串字符串,若匹配成功,最终返回一个数组,数组中的元素就是每个被分割的字符串;若匹配失败,也会返回一个数组,数组中只有一个元素,那就是这个字符串整体。
'1,2,3,4,5,6'.split(/,/) //返回 ['1', '2', '3', '4', '5', '6'] '1,2,3,4,5,6'.split(/\+/) //返回 ['1,2,3,4,5,6']
RegExp对象的方法
RegExp对象定义了两个用于匹配的方法——exec()
和test()
,这两个方法与我们之前讲到的用于模式匹配字符串的方法不同的是,前者是定义在RegExp对象上的方法,并且传入的参数是字符串;而后者是调用字符串的方法,传入的参数是RegExp对象。
- exec()
该方法就跟前面说到的不传入修饰符g的matach()
方法一样,它对字符串执行一个正则表达式,如果匹配失败,返回null;如果匹配成功,则返回一个数组,数组的第一个元素是正则表达式匹配到的字符串,剩下的元素则是子表达式匹配到的字符串,同时该数组也包含index
和input
两个属性。
来看一个例子,体会一下exec()方法的作用
let pattern = new RegExp("java", "g")let ret = pattern.exec("I love javascript and java") //返回["java"] ret.index //返回 7ret.input //返回 I love javascript and java
exec()
与 match()
方法不同的是,不管正则表达式是否使用修饰符g,exec()都只会将第一个匹配到的字符串以及子表达式匹配到的字符串放到数组里返回;而match()方法在没有使用修饰符g时,跟exec()一样,如果使用了修饰符g,则将所有匹配到的字符串都放在数组里一起返回,并且不会返回圆括号里匹配到的字符串,同时,该数组里不包含index
和input
两个属性。
那么这里引发一个疑问,既然不管是否使用修饰符g,exec()方法都只会返回第一个匹配到的字符串,那这个修饰符g有什么用呢?其实我们在前面有说到,RegExp对象内有一个属性叫做 lastIndex,该属性默认为0。当我们调用exec()方法,并且使用了修饰符g进行匹配时,若匹配成功,lastIndex将变为下一次检索开始位置的索引值;若匹配失败,lastIndex则重置为0
let pattern = new RegExp("java", "g")console.log(pattern.lastIndex) //查看lastIndex默认为0let str = "I love javascript and java" pattern.exec(str) //进行第一次检索匹配,返回["java"]console.log(pattern.lastIndex) //此时lastIndex为 4 pattern.exec(str) //进行第二次检索匹配,返回["java"]console.log(pattern.lastIndex) //此时lastIndex为 19 pattern.exec(str) //进行第三次检索匹配,返回nullconsole.log(pattern.lastIndex) //此时lastIndex为 0
从上面这个例子我们能看看到,lastIndex默认为0,表示从字符串的开头开始检索,当我们进行第一次检索时,匹配到了javascript中的java,返回了该字符串,这时lastIndex变为第一次匹配到的字符串的起始位置索引 4;我们进行第二次索引,是从索引 5 开始匹配的,往后检索到字符串末尾的java,并返回该字符串,同时lastIndex变为第二次匹配到的字符串起始位置索引 19;我们进行第三次索引,是从索引 20 开始匹配的,往后匹配,已经无法匹配到对应的字符串了,所以返回一个null,并将lastIndex重置为0,表示下一次检索又从字符串的开头开始检索。
- test()
该方法与exec()类似,该方法也是传入一个字符串作为参数,对该字符串进行检索,如果匹配到了相应的字符串,则返回true;如果没匹配到,则返回false。
let pattern = new RegExp("java", "g")let ret = pattern.test("I love javascript and java") //返回 true
test() 与 exec() 相同的是,如果匹配时使用了修饰符g,test()也会根据对象内部属性 lastIndex 进行检索匹配,这里就不多做说明了。
正则表达式实战应用
(1)判断电话号码格式
应用场景:判断用户输入的电话号码格式是否正确
电话号码格式:1开头,后面跟10位数字
let str = "12356456132" //str为用户输入的电话号码let re = /^1\d{10}$/ if(re.test(str) !== true) { console.log('电话号码格式不正确')}else { console.log('电话号码格式正确')}
(2)判断邮箱格式
应用场景:判断用户输入的邮箱格式是否正确
邮箱格式:第一部分@第二部分,第一部分由字母、数字 和 短横线 - 组成,第二部分由(字母、数字、短横线 - ).cn.com…… 组成
let str = "561325647@qq.com" //用户输入的邮箱let re = /^[\w-\.]+@(\w-?)+(\.\w{2,})+$/if(re.test(str) !== true) { console.log('邮箱格式不正确')}else { console.log('邮箱格式正确')}
(3)判断昵称格式
应用场景:判断用户输入的昵称是否符合规定格式
昵称格式:昵称由字母、数字、下划线组成,必须由字母开头,长度为4-16位
let str = "Lpyexplore233" //用户输入的昵称let re = /^[a-zA-Z][\w_]{3,15}$/if(re.test(str) !== true) { console.log('昵称格式不正确')}else { console.log('昵称格式正确')}
结束语
JavaScript的正则表达式系列文章就到这里结束了,希望对大家有所帮助。