什么是正则表达式
正则表达式是用来从文本中查找出特定的式的一组字符或者符号
正则表达式是针对字符串对象从左到右进行匹配的模式。正则表达式可以从一个基础字符串中根据一定的匹配模式去替换文本中的字符串、校验格式以及提取字符串等等。正则表达式的缩写有regex
、regexp
。
想象你正在写一个应用程序,你想让用户根据你指定的规则去创建用户名。规则如下:
1.包含字母(小写) 2.包含数字(0-9) 3.包含下划线 4.包含连接符号 5.用户名长度在3-12个字符串之间
那么根据以上规则,我们可以书写如下正则表达式:
上述的表达式可以接受的字符串有:lanyoung
、l_young
、lany_1234
、lany_12-34
等等。但是不能匹配ly
,因为字符串长度不符合规则。
基础匹配
正则表达式就是我们用来在文本中执行搜索的字符模式。比如说正则表达式the
的含义就是匹配文本中包含the
的字符串。
“the” => The fat cat sat on
the
mat.
又比如说,正字表达式123
就是用来匹配文本中包含123
的字符串。正则表达式针对字符串的匹配是通过逐个比较正则表达式中的字符以及输入字符串中的每个字符而完成的。正则表达式对大小写很敏感,通常会区分大小写。例如正则表达式the
只会匹配the
的字符串而不会匹配The
、tHe
等字符串。
元字符
元字符是正则表达式的构建块。元字符不代表它们自己,但是会以某种特殊的方式去匹配。有些元字符被写在方括号里会有特殊的含义。
元字符 | 描述 |
---|---|
. | 句号。匹配除换行符以外的任何字符 |
[] | 字符类,匹配任何包含在括号里面的字符 |
[^] | 否定字符类,匹配任何不包含在括号里面的字符 |
* | 匹配前一个符号的0次或多次重复。 |
+ | 匹配前一个符号的1次或多次重复。 |
? | 使该符号的前一个符号可选 |
{n,m} | 对该符号的前一个符号重复匹配至少n次至多m次 |
(xyz) | 字符组。以相同的顺序匹配字符xyz |
| | 匹配该符号的前一个或后一个字符 |
\ | 逃逸符号。 用来匹配被保留的关键符号,例如.、[]、&、$等等。 |
^ | 匹配输入的开头 |
& | 匹配输入的结尾 |
句号
句号.
是最简单的元字符。可以匹配除换行符以外的任何字符。
举个例子:
.ly
:用来匹配以ly
结尾的任何字符。
“.ly” => My name is h
ily
.
字符串集合
字符串集合也可以称作字符类。用方括号来指定字符集合,在字符中用连接符号(-)来指定字符的范围。方括号中的字符顺序无关紧要。
举个例子:
[Tt]
he: 匹配以T
或者以t
开头,且后面跟着h
和e
的字符的字符串。
“[Tt]he” =>
The
car parked inthe
garage.
当句号(.)元字符在方括号中的时候意味着将它仅当作一个句号字符去匹配。
举个例子:
ar[.]
: 用来匹配以a
字符开头,后面跟着r
字符,以.
结尾的字符。
“ar[.]” => A garage is a good place to park a c
ar.
否定字符集合
通常情况下,插入字符表示匹配一个字符串的开始,但是存在于方括号中时,则会否定方括号的中的字符,什么意思呢? 就是不会匹配方括号中的字符。
举个例子:
[^c]ar
: 代表匹配除字符c
开头,但是后面跟着a
和r
字符的字符串。
”[^c]ar” => The car
par
ked in thegar
age.
重复
+
、*
、?
这些元字符是用来指定子模式可以出现多少次。这些元字符在不同的场景下会有不同的表现。
*
*
符号会匹配该符号前的字符0次或者多次。正则表达式a*
代表匹配字符a
0次或者多次。但是如果出现在字符类或者集合的后面那么就会重复匹配整个字符集合。正则表达式[a-z]*
代表匹配任意数量的小写字符。
“[a-z]*” => S
he is a beautiful girl
.
*
符号可以用来与元字符.
相结合使用。例如.*
为匹配任意字符串的字符。*
还可以与空格字符\s
结合使用用来匹配一串空白字符串。
举个例子:
\s*cat\s*
=> The fatcat
sat on the concat
enation.
+
+
符号会匹配该符号前的字符1次或多次。正则表达式a+
代表匹配字符a
一次或者多次。
正则表达式b.+l
代表匹配字符b
开头,后面至少跟着一个字符,随后跟着一个字符l
。其中要说明的是匹配的字符l
默认匹配文本中最后一个出现的字符l
。
“b.+l” => She is a
beautiful girl
.
?
正则表达式中元字符?
可以让该符号前的字符变为可选字符。这个元字符匹配该符号前的字符0次或者1次。
正则表达式[T]?he
代表字符T
为可选择字符,后面跟着字符h
,然后跟着字符e
。
“[T]?he” =>
The
car is parked in the
garage.
花括号 {}
该元字符也被称作为量词,通常用来指定字符或者一组字符类可以重复的次数。
正则表达式[0-9]{2,3}
代表匹配至少两个数字但是最多3个。
“[0-9]{2,3}” => The number was 9.
999
7 but we rounded it off to10
.0.
我们也可以将花括号中的第二个参数忽略。
正则表达式[0-9]{2,}
代表匹配至少两个数字。
“[0-9]{2,}” => The number was 9.
9997
but we rounded it off to10
.0.
正则表达式[0-9]{3}
代表匹配3个数字。
“[0-9]{3}” => The number was 9.
999
7 but we rounded it off to 10.0.
字符组 ()
字符组是一组被写在括号(…)里面的子模式。就想我们之前所讨论的。当一个量词被放在一个字符后面的时候那么它会匹配这个字符指定的次数,但是如果一个量词被放在一个字符组后面那么就会对整个字符组匹配指定的次数。
正则表达式(ab)*
代表将匹配ab
0次或者更多次。
我们也可以添加替换元字符(|
)在字符组中。
正则表达式(c|g|p)ar
代表匹配字符c
、g
或者p
,后面跟着字符a
,再后面跟着字符r
。
“(c|g|p)ar” => The
car
ispar
ked in thegar
age.
非捕捉组
非捕获组是只匹配对应的字符而捕获组的捕获组。非捕获组通常在括号内用?
表示,后面接一个:
。
正则表达式(?:c\|g\|p)ar
代表匹配字符c
、g
、p
,后面跟着字符a
,再后面跟着字符r
。匹配的效果跟(c|g|p)ar
一样,但是不同的是不会生成捕获组。
”(?:c|g|p)ar” => The
car
ispar
ked in thegar
age.
替换符 |
在正则表达式中,字符|
通常被定义成替换符号。类似与多个条件中的or
语句。现在,你可能认为字符类以及替换符号是相同的工作方式。但是两者之间最大的不同是字符类是在字符层面上工作而替换符号是在表达式层面进行工作的。
正则表达式(T|t)he|car
代表匹配The
或者the
或者car
。
“(T|t)he|car” =>
The
car
is parked inthe
garage.
逃逸符号 \
反斜杠\
通常将该符号的后一个字符转义成文本字符。这样可以允许你去匹配本来被保留的一些元字符符号,例如:*
、|
、[
、]
、^
、$
、?
、+
、{
、}
等等。
比如说元字符.
通常用来匹配除换行符以外的任意字符。如果现在你想匹配字符串中的.
。那么正则表达式就要写成\.
“(f|c|m)at.?” => The fat cat sat on the mat.
锚点
在正则表达式中,我们通常会用锚点来检查输入的字符串中所匹配的表示是否是开始标志或者结束标志。锚点有两种类型:第一种类型是脱字符号^
,用来检查所匹配的字符是否是字符串中的开头。另外一种类型是美元符号$
,用来检查所匹配的字符是否是字符串中的结尾。
脱字符号^
脱字符号通常用于检查所匹配的字符是否是字符串中的开头。如果我们使用正则表达式^a
到字符串abc
中,那么就会得到的匹配的结果a
。但是如果我们使用正则表达式^b
到字符串abc
中,那么就不会匹配到任何结果,因为字符串不是以b
开头的。
可以比较如下两个正则表达式所匹配的结果:
“(T|t)he” =>
The
car is parked inthe
garage.
”^(T|t)he” =>
The
car is parked in the garage.
美元符号$
美元符号$
通常用于检查所匹配的字符是否是字符串中的结尾。
可以比较如下两个正则表达式所匹配的结果:
“(at.)” => The fat c
at.
sat.
on the mat.
“(at.)$” => The fat cat. sat. on the m
at.
快捷字符集合
正则表达式针对经常用到的字符集合提供了更短的字符。为常用的正则表达式提供更短的字符。短字符如下:
短字符 | 描述 |
---|---|
. | 除换行符以外的任何字符 |
\w | 匹配字母、数字、下划线以及连接符号:[a-zA-z0-9-_] |
\W | 匹配除了字母、数字、下划线以及连接符号之外的符号:[^\w] |
\d | 匹配数字:[0-9] |
\D | 匹配非数字:[^0-9] |
\s | 匹配空格字符:[\t\n\f\r\p{Z}] |
\S | 匹配非空格字符:[^\t] |
Lookaround
Lookbehind
和Lookahead
也称作Lookaround
是特定类型的捕获组(用于匹配模式但是不包含在匹配列表中)。当我们的条件是这个模式的前面一个或者后面一个模式时可以使用Lookaround
。
举个例子,当我们相匹配输入字符串$4.44 and $10.88
中的$
后面的数字的时候,我们可以用正则表达式(?>=\$)[0-9\.]*
来查找输入字符串中的数字4.44
和10.88
”(?>=$)[0-9.]*” > $
4.44
and $10.88
Lookaround
的符号有如下几种:
符号 | 描述 |
---|---|
?= | Positive Lookahead |
?! | Negative Lookahead |
?<= | Positive Lookbehind |
?<! | Negative Lookahead |
Positive Lookahead
“(T|t)he(?=\sfat)” =>
The
fat cat sat on the mat.
Negative Lookahead
“(T|t)he(?=\sfat)” => The fat cat sat on
the
mat.
Positive Lookbehind
”(?<=(T|t)he\s)(.at)” => The
fat
cat thesat
on themat
.
Negative Lookahead
”(?<!(T|t)he\s)(.at)” => The fat
cat
the sat on the mat.
Flags
Flags
也称作修饰符。因为它们修改了正则表达式的输出。这些标志可以以任何顺序或者组合方式使用,它们也是正则表达式的一部分。
Flag | 描述 |
---|---|
i | 忽略所匹配字符的大小写 |
g | 全局搜索 |
m | 多行匹配 |
大小写不敏感
i
修饰符用于执行忽略大小写的匹配。
正则表达式:/The/gi
代表查找输入字符串中以大写字母T
开头,后面跟着字符h
再后面跟着字符e
的字符集。i
修饰符代表忽略开头字符T
的大小写。
“/The/gi” =>
The
fat cat sat onthe
mat.
“/The/g” =>
The
fat cat sat on the mat.
全局搜索
g
修饰符代表查找整个字符串中与其匹配的模式,而不是查找到第一个就停止继续查找。
正则表达式:/.(at)/g
代表查找所有输入字符串中以除换行符以外的任意字符开头,后面跟着字符a
再后面跟着字符t
的字符集。
”/.(at)/g” => The
fat
cat
thesat
on themat
.
”/.at/” => The
fat
cat the sat on the mat.
多行匹配
m
修饰符通常用于进行多行匹配。正如我们之前讨论的,元字符^
以及$
是用来检查所匹配的模式是输入还是结尾。但是这仅仅只能对单行如此。如果我们想检查每一行所匹配的模式是输入还是结尾,那么我们可以用m
修饰符。
> "/.at(.)?$/gm" => The fat `cat`
the `sat`
on the `mat.`
> "/.at(.)?$/" => The fat cat
the sat
on the `mat.`
Greedy vs lazy match
默认情况下,正则表达式是积极匹配。意识是尽可能的多匹配。我们可以用?
来替换成懒匹配。
”/(.*at)/” =>
The fat cat the sat on the mat
.
”/(.*?at)/” =
The fat
cat the sat on the mat.