前言
本文介绍了对正则表达式的基本使用与总结,希望之后再用到正则时,不再面向搜索引擎编程😃。
首先推荐两个比较好的学习正则的网站:
正则对象方法
| 方法名 | 描述 |
|---|---|
| exec | 根据正则查找匹配的字符,返回匹配到的第一个字符的信息所组成的数组(未匹配则返回null) |
| test | 根据正则查找匹配的字符,匹配成功返回true,否则返回false |
exec
使用方法:
const regExp = /h/;
console.log(regExp.exec('hello'));
//[0: "h", groups: undefined, index: 0, input: "hello"]
test
使用方法与exec一样:
const regExp = /h/;
console.log(regExp.test('hello'));
// true
用于正则匹配的String方法
| 方法名 | 描述 |
|---|---|
| search | 根据正则查找匹配的字符, 返回第一个匹配的字符的索引,没有匹配到则返回-1.注意:因为search会忽略修饰符g,所以它不支持全局搜索 |
| replace | 根据正则查找匹配的字符,并且使用替换字符串替换掉匹配到的字符串,返回一个被替换后的新字符串,原字符串不变 |
| match | 根据正则查找匹配的字符,返回一个由匹配结果组成的数组 |
| split | 根据正则查找匹配的字符,并根据匹配结果分隔原始字符串,返回一个由被分割后的结果所组成的数组 |
search
语法:
str.search(regexp) // regexp:正则表达式
使用方式:
const regExp = /h/;
const str = 'elho';
console.log(str.search(regExp)); //返回匹配结果的索引: 2
replace
语法:
str.replace(regexp|substr, newSubStr|function) // regexp:正则表达式
使用方式:
const regExp = /h/;
const str = 'elho';
console.log(str.replace(regExp, 'k')); //elko
match
语法:
str.match(regexp) // regexp:正则表达式
使用:
const regExp = /h/;
const str = 'elho';
console.log(str.match(regExp));
// [0: "h", groups: undefined, index: 2, input: "elho"]
当不使用全局模式匹配时,match返回的结果与正则对象的exec方法一样。不同的是,当使用全局模式匹配时,match会返回一个由匹配结果组成的数组,而exec方法始终返回第一个匹配到的字符的信息。
const regExp = /h/g;
const str = 'elhoh';
console.log(str.match(regExp)); // ['h', 'h']
console.log(regExp.exec(str)); // [0: "h", groups: undefined, index: 2, input: "elho"]
split
语法:
str.split(separator|regexp, limit)
regexp:正则表达式
limit: 一个整数,限定返回的分割片段数量,例如:split结果为[1, 2, 3],传入的limit为2,那么只返回结果数组的前面两位,最终返回的结果则为:[1, 2]
使用:
const regExp = /\s?;\s?/g;
const str = 'Harry ;Fred ; Rigby ;';
console.log(str.split(regExp)); // ['Harry', 'Fred', 'Rigby', '']
console.log(str.split(regExp, 1)); // ['Harry']
正则表达式标志
正则表达式有六个可选参数,允许全局和不分大小写搜索等。这些参数既可以单独使用也能以任意顺序组合一起使用。
| 标志 | 描述 |
|---|---|
| g | 全局搜索 |
| i | 不分大小写 |
| m | 全局搜索 |
| s | 允许.匹配换行符 |
| u | 使用unicode编码模式进行匹配 |
| y | 执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始 |
使用方法
单个使用:
const regExp = /h/g;
const str = 'helho';
console.log(str.match(regExp)); // ['h', 'h']
多个组合使用:
const regExp = /h/gi;
const str = 'helHo';
console.log(str.match(regExp)); // ['h', 'H']
字符类
字符组
字符组([]):允许匹配一组可能出现的字符。
例如:
在[]中放置需要匹配的不同字符:J,j。意思就是需要配置:javaScript或者JavaScript。
区间
有些字符组非常大,比如我们需要匹配所有的数字,那么我们的字符组就需要这样写:[0123456789]。需要匹配所有的英文字母,那么我们就必须从a-z和A-Z都写一遍,这样的做法十分麻烦,所以正则中可以在[]中使用-符号来代表区间。
- 如果我们需要匹配数字,那么使用区间可以这样写:
[0-9]。 - 如果我们需要配小写字母,那么使用区间可以这样写:
[a-z]。 - 如果我们需要配大写字母,那么使用区间可以这样写:
[A-Z]。 - 对上述三种都需要匹配,那么可以这样写:
[0-9a-zA-Z]。
例如:
取反
有时我们希望排除某些字符来匹配其它字符,比如:我们现在希望匹配除了2和4其它所有的数字,按照正常字符组来写,我们会写成这样:[01356789]。如果是比较大的字符组的话,这样的写法会很麻烦,所有正则中提供了字符组取反的功能,在字符组开头加上^。上面的例子使用取反的话就可以这样写:[^24]:
如图:
匹配特殊字符-转义
在正则表达式中许多标点符号都具备特殊的含义:
[]: 表示字符组-: 表示区间 ......
当我们需要匹配字符中的[],-或其他特殊符号时,我们需要将特殊字符进行转义操作,即: \-,\[\]。
如图:
特殊字符
快捷字符
快捷字符:它的作用就是可以使用字符来代替某些常用的正则表达式。
| 字符 | 含义 |
|---|---|
. | 匹配除换行符之外的任何单个字符,一个小数点代表一个任意字符,这个字符可以是数字、符号、中英文等 |
\w | (小写w)匹配一个单字字符(字母、数字或者下划线),等价于 [A-Za-z0-9_]。 |
\W | (大写w)匹配一个非单字字符。等价于 [^A-Za-z0-9_] |
\s | (小写s)匹配一个空白字符,包括空格、制表符、换页符和换行符 |
\S | (大写s)匹配一个非空白字符 |
\d | 匹配一个数字,等价于[0-9]。 |
\D | 匹配一个非数字,等价于[^0-9]。 |
锚字符
锚字符:它的作用就是可以确定某些需要匹配的字符的位置。
| 字符 | 含义 |
|---|---|
^ | 匹配字符串开头,或者当使用多行标志(m)时,匹配一行的开头。 这个会匹配到位置,而不是字符。 |
$ | 匹配字符串结尾,或者当使用多行标志(m)时,匹配一行的结尾。 这个会匹配到位置,而不是字符 |
\b | 匹配一个词的边界。边界可以理解为两个“字”字符之间是否有其它非“字”字符,如:空格,符号等,如果存在空格,符号等非“字”字符,那么该字符便存在边界,正则便可以根据边界匹配到该字符 |
\B | 匹配一个非单词边界 |
重复
当我们期望一个字符连续匹配好几次,比如匹配手机号或者身份证的时候,使用之前的写法,我们匹配手机号只能这样写:/\d\d\d\d\d\d\d\d\d\d\d/需要写11个\d来表示11位的数字,这样做法十分麻烦,而且不够灵活,所以我们使用重复的字符语法来匹配出现多次的元素。
重复字符语法
| 字符 | 含义 |
|---|---|
{n,m} | 匹配前一项字符至少n次,小于等于m次 |
{n,} | 匹配前一项字符n次或更多次 |
{n} | 匹配前一项字符n次 |
? | 匹配前一项字符0次或1次,也就是说前一项字符是可选的,等价于{0,1} |
+ | 匹配前一项字符1次或多次,等价于{1,} |
* | 匹配前一项字符0次或多次,等价于{0,} |
{n,m}字符语法-重复区间
有些时候,我们不确定匹配字符的重复次数,比如说:座机的区号,需要校验中国和俄罗斯的座机号。中国的是:86-10086,俄罗斯的是:7-10000。这时候就需要用到重复区间{m,n}。
这时,我们需要匹配的电话号码的区号可能是1位也可能是2位,后面是5位数字,那么我们则需要这样写:\d{1,2}\-\d{5}。
如图:
首先匹配1到2位的数字,然后需要匹配-,最后匹配5位数字。
{n,}字符语法-开闭区间
有些时候,我们不确定匹配字符的重复次数,比如说:座机的区号,需要校验多个国家的。他们区号和号码的位数都不确定,只有固定的格式xxx-xxxx。这时候就需要用到我们的开闭区间{n,}。
例如:
匹配至少1位区号,然后匹配-符号,最后匹配至少5位号码。
{n}字符语法-重复
这个字符语法比较简单,就是将前面的字符匹配n次。
例如:
\d代表数字,后面加上重复字符语法{3},表示连续匹配3个数字。
? 字符语法-可选
?字符语法表示前面一个字符将匹配1次或0次。
例如:
在l后面放置了可选字符语法,表示有l的时候则匹配,匹配的结果为hello,没有的时候则不匹配,匹配结果为helo。
+字符语法与*字符语法
+字符语法:匹配前一项字符1次或多次,等价于{1,}。
例如:
/a\d+/g表示在a字符串后面需要跟着至少1个数字的字符才能被匹配。
在这个例子中我们的字符串为a不符合正则表达式要求,所以没有被匹配到。
再看一个例子:
在上一个例子的基础上,我们在a后面添加了多个数字,符合正则表达式。
*字符语法:匹配前一项字符0次或多次,等价于{0,}。
例如:
与+字符语法不同,*字符语法表示在a后面至少跟着0个或更多个数字,就会被正则所匹配到。
分组
分组的字符语法:
| 字符 | 含义 | |
|---|---|---|
(x) | 匹配x项并且记住匹配项,使用$n表示被记住的匹配项 | |
(?:x) | 匹配x项,但是不记住匹配项 | |
| `x | y` | 匹配x或y |
\n | 引用分组 |
捕获分组
捕获分组:就是匹配()中的字符,并且可以将匹配到的结果记住,通过$n来获取匹配结果。在捕获表达式中第一个捕获分组所得结果使用$1表示,第二个使用$2表示,以此类推第n个分组的结果使用$n表示。
例如:
// (\d{3}) 是第一个分组 对应 $1
// (\d{4}) 是第二个分组 对应 $2
const regexp = /(\d{3})-(\d{4})/g;
const str = '123-4567';
regexp.exec(str);
console.log(RegExp.$1); // 123
console.log(RegExp.$2); // 4567
非捕获分组
非捕获分组与捕获分组用法相同,不同的是匹配到的结果不会被记录,通过$n无法获取结果。
例如:
// (\d{3}) 是第一个分组 对应 $1
// (\d{4}) 是第二个分组 对应 $2
const regexp = /(?:\d{3})-(?:\d{4})/g;
const str = '123-1234';
regexp.exec(str);
console.log(RegExp.$1); // ''
console.log(RegExp.$2); // ''
引用分组
引用分组用于在一个字符中匹配的子字符规则多次出现。
例如:
<font>文字</font>
需要匹配html标签,将标签内容提取出来。
我们可以这样写:
可以看到,我们一共有两个分组:
(\w+): html标签的分组,序号为1(.+): 标签内容的分组,序号为2
最后我们在闭合标签中使用了\1,去引用序号为1的分组,确保了html标签的一致。最后我们可以使用RegExp.$2获取出标签的内容。
或者条件
或者条件是使用|符号表示的与字符组类似,都是匹配多个选项。但是不同的是,字符组中的匹配项只能以单个字符的形式匹配,而或者条件的条件则可以是多个字符组成。
例如:
/[abc]/g // 字符组
/abc|asd|dfg/g // 或者条件
先行断言
正向先行断言
正向先行断言: (?=表达式),如:x(?=y),从左向右看,x后面必须跟着y才满足正向先行断言。
例如:
我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
需要取出喜欢两个字,需要喜欢后面有“你”,这个时候就要这么写:喜欢(?=你):
反向先行断言
反向先行断言: (?!表达式),如:x(?!y),从左向右看,x后面保证不跟着y才满足反向先行断言。
例如:
我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
需要取出喜欢两个字,需要喜欢后面没有“你”,这个时候就要这么写:喜欢(?!你):
后行断言
正向后行断言
先行断言和后行断言只有一个区别,即先行断言从左往右看,后行断言从右往左看。
正向后行断言: (?<=表达式),如:(?<=y)x,从右向左看,x前面保证跟着y才满足正向后行断言。
例如:如果要取出喜欢两个字,要求喜欢的前面有我,后面有你,这个时候就要这么写:(?<=我)喜欢(?=你)。
反向后行断言
反向后行断言: (?<!表达式),如:(?<!y)x,从右向左看,x前面保证不跟着y才满足反向后行断言。
例如:如果要取出喜欢两个字,要求喜欢的前面没有我,后面没有你,这个时候就要这么写:(?<!我)喜欢(?!你)。
实战
到这里正则的基本知识都学习完成了,那我们来做点题目自我检测一下。
使用正则判断一个字符是否为小数
题目:
需要匹配:
1.211.220.1192.123456
不需要匹配:
112.1212.12.12.1.1.1.1999
首先分析一下小数的特点:
- 以数字开头
- 只有一位小数点
- 以数字结尾
答案:/^\d+\.\d+$/g
我们来分析一下这个正则表达式:
^\d+:表示匹配至少一个或更多个以数字开头的字符。\.:使用字符转义,匹配字符小数点\d+$:表示匹配至少一个或更多个以数字结尾的字符
使用正则校验手机号码格式
题目:
校验手机号码格式是否正确?
规则:
- 必须是
11位的数字; - 第一位数字必须以
1开头,第二位数字可以是[3,4,5,7,8]中的任意一个,后面9个数是[0-9]中的任意一个数字。
答案:/^1[3,4,5,7,8]\d{9}/g
我们来分析一下这个正则表达式:
^1:表示匹配开头位置为1的字符[3,4,5,7,8]:表示匹配第二个字符是3,4,5,7,8其中之一的字符\d{9}:表示匹配9个数字