对于正则表达式,我平时用到的话基本上就是去搜索引擎上直接搜索,因位我觉得就没有什么规律。但是最近复习es6里面有正则的部分,所以我又把正则表达式看了一遍。这次再考的时候好像很多东西其实是可以看完之后就理解了同时记住的,让我们一起来看看如何理解着记住这些东西:
从字符出发
我们学习一个系统化的知识,一定要从其基础构成来了解。正则表达式的基本组成元素可以分为:字符和元字符。字符很好理解,就是基础的计算机字符编码,通常正则表达式里面使用的就是数字、英文字母。而元字符,也被称为特殊字符,是一些用来表示特殊语义的字符。如^表示非,|表示或等。利用这些元字符,才能构造出强大的表达式模式(pattern)。接下来,我们就来从这些基本单位出发,来学习一下如何构建正则表达式。
单个字符
最简单的正则表达式可以由简单的数字和字母组成,没有特殊的语义,纯粹就是一一对应的关系。如想在'apple'这个单词里找到‘a'这个字符,就直接用/a/
这个正则就可以了。
但是如果想要匹配特殊字符的话,就得请出我们第一个元字符**``**, 它是转义字符字符,顾名思义,就是让其后续的字符失去其本来的含义。举个例子:
我想匹配*
这个符号,由于*
这个符号本身是个特殊字符,所以我要利用转义元字符``来让它失去其本来的含义:
/*/
如果本来这个字符不是特殊字符,使用转义符号就会让它拥有特殊的含义。我们常常需要匹配一些特殊字符,比如空格,制表符,回车,换行等, 而这些就需要我们使用转义字符来匹配。为了便于记忆,我整理了下面这个表格,并附上记忆方式:
特殊字符 | 正则表达式 | 记忆方式 |
---|---|---|
换行符 | \n | new line |
换页符 | \f | form feed |
回车符 | \r | return |
空白符 | \s | space |
制表符 | \t | tab |
垂直制表符 | \v | vertical tab |
回退符 | [\b] | backspace,之所以使用[]符号是避免和\b重复 |
多个字符
单个字符的映射关系是一对一的,即正则表达式的被用来筛选匹配的字符只有一个。而这显然是不够的,只要引入集合区间和通配符的方式就可以实现一对多的匹配了。
在正则表达式里,集合的定义方式是使用中括号[
和]
。如/[123]/
这个正则就能同时匹配1,2,3三个字符。那如果我想匹配所有的数字怎么办呢?从0写到9显然太过低效,所以元字符-
就可以用来表示区间范围,利用/[0-9]/
就能匹配所有的数字, /[a-z]/
则可以匹配所有的英文小写字母。
即便有了集合和区间的定义方式,如果要同时匹配多个字符也还是要一一列举,这是低效的。所以在正则表达式里衍生了一批用来同时匹配多个字符的简便正则表达式:
匹配区间 | 正则表达式 | |
---|---|---|
除了换行符之外的任何字符 | . | 句号,除了句子结束符 |
单个数字, [0-9] | \d | digit |
除了[0-9] | \D | not digit |
包括下划线在内的单个字符,[A-Za-z0-9_] | \w | word |
非单字字符 | \W | not word |
匹配空白字符,包括空格、制表符、换页符和换行符 | \s | space |
匹配非空白字符 | \S | not space |
循环与重复
一对一和一对多的字符匹配都讲完了。接下来,就该介绍如何同时匹配多个字符。要实现多个字符的匹配我们只要多次循环,重复使用我们的之前的正则规则就可以了。那么根据循环次数的多与少,我们可以分为0次,1次,多次,特定次。
0 | 1
元字符?
代表了匹配一个字符或0个字符。设想一下,如果你要匹配color
和colour
这两个单词,就需要同时保证u
这个字符是否出现都能被匹配到。所以你的正则表达式应该是这样的:/colou?r/
。
>= 0
元字符*
用来表示匹配0个字符或无数个字符。通常用来过滤某些可有可无的字符串。
>= 1
元字符+
适用于要匹配同个字符出现1次或多次的情况。
特定次数
在某些情况下,我们需要匹配特定的重复次数,元字符{
和}
用来给重复匹配设置精确的区间范围。如'a'我想匹配3次,那么我就使用/a{3}/
这个正则,或者说'a'我想匹配至少两次就是用/a{2,}/
这个正则。
以下是完整的语法:
- {x}: x次
- {min, max}: 介于min次到max次之间
- {min, }: 至少min次
- {0, max}: 至多max次
由于这些元字符比较抽象,且容易混淆,所以我用了联想记忆的方式编了口诀能保证在用到的时候就能回忆起来。
匹配规则 | 元字符 | |
---|---|---|
0次或1次 | ? | 是不是和三元有点像?0或者1 |
0次或无数次 | * | 通配符,全部 但是这里还有个0次 |
1次或无数次 | + | 一直加下去就是无数,但是还有个1次 |
特定次数 | {x}, {min, max} | 这就是一个区间啊,左边是最小值右边是最大值 |
位置边界
上面我们把字符的匹配都介绍完了,接着我们还需要位置边界的匹配。在长文本字符串查找过程中,我们常常需要限制查询的位置。比如我只想在单词的开头结尾查找。
单词边界
单词是构成句子和文章的基本单位,一个常见的使用场景是把文章或句子中的特定单词找出来。如:
The cat scattered his food all over the room.
我想找到cat
这个单词,但是如果只是使用/cat/
这个正则,就会同时匹配到cat
和scattered
这两处文本。这时候我们就需要使用边界正则表达式\b
,其中b是boundary的首字母。在正则引擎里它其实匹配的是能构成单词的字符(\w)和不能构成单词的字符(\W)中间的那个位置。
上面的例子改写成/\bcat\b/
这样就能匹配到cat
这个单词了。
字符串边界
匹配完单词,我们再来看一下一整个字符串的边界怎么匹配。元字符^
用来匹配字符串的开头。而元字符$
用来匹配字符串的末尾。注意的是在长文本里,如果要排除换行符的干扰,我们要使用多行模式。试着匹配I am scq000
这个句子:
I am xiaodai.
I am xiaodai.
I am xiaodai.
我们可以使用/^I am xiaodai.$/m
这样的正则表达式,其实m是multiple line的首字母。正则里面的模式除了m外比较常用的还有i和g。前者的意思是忽略大小写,后者的意思是找到所有符合的匹配。
最后,总结一下:
边界和标志 | 正则表达式 | 记忆方式 |
---|---|---|
单词边界 | \b | boundary |
非单词边界 | \B | not boundary |
字符串开头 | ^ | |
字符串结尾 | $ | |
多行模式 | m标志 | multiple |
忽略大小写 | i标志 | ignore |
全局模式 | g标志 | global |