- 模式:术语
模式
用来表示实际的正则表达式 - regex的作用:匹配一些文本,或者匹配然后替换一些文本
- regex的使用:大多数的软件,编程语言与IDE中已经内置了regex
- regex基本性质:
1. 匹配结果:大多数正则表达式只返回第一个匹配结果,且匹配到的结果为与某个模式串
2. 大小写问题: 正则表达式的匹配结果区分大小写,但正则表达式语法不区分大小写。
3. 匹配特殊字符:若需要匹配特殊字符(如元字符),则必须在元字符前面加一个\(反斜杠)来对其进行转义(连字符-特殊)。(对于斜杠/在许多regex的实现里无需转义,但有些则需要转义。)
文章目录
一、静态文本匹配
任何的文本都可以作为单独的正则表达式
二、任意匹配
Ⅰ.单字符匹配
正则表达式可用元字符来匹配一类字符。
常见元字符:
1. .
字符
.
字符可以匹配任意单个字符、字符、数字甚至是.字符本身;在一个正则表达式里可出现多个.
字符,它们既可以连续出现,也可以各自出现在模式的不同位置。
.
未必可以匹配所有字符,在大多数正则表达式的实现里,.
不能匹配换行符。
2. [ ]
字符
[ ]
字符用来定义一个字符集合,所对应的字符必须匹配`字符集合中的某个成员(并非全部)。
字符集合在不需要区分字母大小写(或只需匹配某个特定部分)的搜索操作里比较常见。如:
<[Tt][Ii][Tt][Ll][Ee]>
字符集合与
|
(或操作符):集合只是匹配一个字符,而|
匹配的是左右两边字符串中的一个。
3. -
字符
使用字符集合是,会频繁用到一些字符区间(0~9、A~Z等),为简化字符区间的定义(不用在[ ]
内将每个元素都列出来),正则表达式提供了连字符-
来定义字符区间。
[ ]
定义的为字符集合,-
定义的为字符区间。
- 定义一个字符区间的方法:①将所有的字符都列出来 ②使用连字符。
- 连字符
-
只有出现在[
和]
之间才是元字符,在[ ]
之外的-
表示其自身。故只有在[ ]
外的-
不需要转义。
- 字符区间实际上是ASCII字符表里首字符到尾字符的所有字符。
- 同一个字符集合内可定义多个字符区间。如:
[a-zA-z0-9]
表示匹配任一英文字母或数字
4.^
字符
^
用在字符集合内表示排除指定的字符外的所有字符。
^
可与-
搭配使用
^
的效果将作用于字符集合内的所有字符或字符区间,而非仅限于紧跟在^
后面的字符或字符区间。
5.空白字符
元字符 | 说明 |
---|---|
[\b] | Backspace键 |
\r | 回车符(Enter) |
\n | 换行符 |
\t | 制表符(Tab) |
\f | 换页符 |
\v | 垂直制表符 |
Windows将
\r\n
即一个“回车+换行”的组合作为文本行的结束标记
Unix/Linux与Mac OSX系统使用一个
\n
作为标记,理想的regex应兼容以上两种情况
6.匹配特定的字符类型
①数字与非数字
元字符 | 说明 |
---|---|
\d | 任何一个数字字符(等价于[0-9] ) |
\D | 任何一个非数字字符(等价于[\^0-9] ) |
②字母数字与非字母数字
元字符 | 说明 |
---|---|
\w | 任何一个字母数字字符(大小写均可),或下划线字符(等价于[a-zA-Z0-9_] ) |
\W | 任何一个非字母数字字符与非下划线字符(等价于[\^a-zA-Z0-9_] ) |
这里的字母数字包括字母(大小写)、数字、下划线。
③空白与非空白
元字符 | 说明 |
---|---|
\s | 任何一个空白字符 |
\S | 任何一个非空白字符 |
注:用来匹配退格字符的
[\b]
元字符不在\s的覆盖范围内,\S也没有将其排除。
④八进制或十六进制数值
- 十六进制:regex里,十六进制数值要用前缀\x给出。
- 八进制:regex里,八进制数值要用前缀\0给出。
有些正则表达式允许适用
\c
来指定控制字符,如\cz
匹配Ctrl-Z
⑤使用POSIX字符类
字符类 | 说明 |
---|---|
[:alnum:] | 任何一个字母或数字(等价于[a-zA-Z0-9] ) |
[:alpha:] | 任何一个字母(等价于[a-zA-Z] ) |
[:space:] | 任何一个空白字符,包括空格(等价于[\f\n\r\t\v ] ) |
[:blank:] | 空格或制表符(等价于[\t ] ) |
[:cntrl:] | ASCII控制字符(ASCII 0到32,再加上127) |
[:dighit:] | 任何一个数字 |
[:print:] | 任何一个可打印字符 |
[:graph:] | 和[:print:] 一样,但不包括空格 |
[:lower:] | 任何一个小写字母(等价于[a-z] ) |
[:upper:] | 任何一个大写字母(等价于[A-Z] ) |
[:punct:] | 既不属于[:alnum:] ,也不属于[:cntrl:] 的任何一个字符 |
[:xdigit:] | 任何一个十六进制数子(等价于[a-fA-F0-9] ) |
其中
[:
与:]
是POSIX字符自带的;若需表示POSIX字符集合,则模式需以[[
开头,以]]
结束,外层的[ ]用来定义一个字符集合,内层的 [ 和 ] 是POSIX字符类本身的组成部分。
Javascript中不支持在正则表达式中使用POSIX字符。
Ⅱ. 重复匹配
正则表达式中可用元字符匹配数量未知个字符。
常见匹配模式:
1.一个或多个字符
+
匹配一个字符或字符集合的一次或多次重复,只需在需匹配的字符或字符集合后面加上一个+
即可。
- 对于字符集合的重复匹配,匹配到的多个字符无需相同,如
[0-9]
匹配的是任意一串数字。
+
是一个转义字符,如果需要匹配+
本身,则需使用\
转义。
- 当在字符集合里使用的时候,像
.
和+
这样的字符将被解释为普通字符,无需转义(与-
相反)。
2.零个或多个字符
*
匹配一个字符或字符集合的零次或多次重复,可以将*
理解为一种“使其可选”的元字符。
3.零个或一个字符
?
匹配一个字符或字符集合的零次或一次出现,?
适合匹配一段文本中的可选字符。(与*
的可选有区别)
应用:Unix/Linux 系统上使用
\n
来表示行结束,于是可以使用\r?\n
的模式来同时适配Windows与Unix/Linux系统。
4.具体的重复匹配
{num}
匹配一个字符或字符集合num次。
5.区间范围匹配
{num,num2}
为重复匹配设定一个区间范围,匹配一个字符或字符集合最少num1次,最多num2次。
6.至少n次匹配
{num, }
指定至少匹配一个字符或字符集合num次。(切记不要遗漏,
,否则模式的含义由至少匹配n次变为只匹配n次)
- 重复的范围可以由0开始。
+
、*
、?
等量词都能用{ }
的方式实现。
{
与}
是元字符,若需要匹配自身,则需要用\
对它们进行转义,但很多情况下,没有进行转义也能正确地使用它们;然而为了避免不必要的麻烦,最好不要依赖这种行为。
7.贪婪与懒惰
对于在重复次数没有上限的重复匹配,其量词有两种类型:①贪婪型:尽可能多地匹配字符;②懒惰型:尽可能少地匹配字符。
例:
文本: This offer is not availavle to customers living in <b>AK</b> and <b>HI</b>.
正则表达式:<[Bb]>.*<\/[Bb]>
贪婪型:<b>AK</b> and <b>HI</b>
懒惰型:<b>AK</b>
与<b>HI</b>
在默认情况下使用的量词都为贪婪型,为使用懒惰型量词,可在贪婪型量词的后面加上"?"。
贪婪型量词 | 懒惰型量词 |
---|---|
+ | +? |
* | *? |
{n, } | {n, }? |
Ⅲ.位置匹配
1.单词匹配
单词边界:其本质上是一个字符(能被\W
匹配的字符,即既非字母数字字符,也非下划线字符。)
①\b
元字符
指定单词边界,使用\bword\b
可以在文本匹配到一个单词(前后都为空格)。
该方式不仅可以匹配前后都是空格的单词情况,还可以匹配到前后都是非字母数字、下划线字符的情况。
②\B
元字符
指定非单词边界。
例:对于文本abcdefg,模式
\Bcde\B
能够正确地匹配到cde
;而对于文本+=cde.*则不能正确匹配。因\B
指定匹配到的字串必须以非单词边界(能被\w匹配的字母数字下划线)作为开头或结尾。
对于有些正则表达式实现,其提供
\<
与\>
元字符分别匹配单词开头与结尾。
2.字符串边界
^
表示在字符串开头进行匹配,$
在字符结尾进行匹配。
这里的边界指的都是文本中的边界(其自然也应出现在模式的开头与结尾)。
从这里可看出,有些元字符拥有多种用途,当
^
出现在[]
间时,且紧跟在[
后时,其表示的是排除字符集合;当出现在模式串的开头时,^
匹配的是字符串的起始位置。
3.多行模式
(?m)
可用于启用多行模式,多行模式使regex引擎将换行符视为字符串分隔符;这样一来,^
即可匹配字符串开头,也可以匹配换行之后的起始位置;$
不仅能匹配字符串结尾,还能匹配换行符之后的结束位置。
在使用时,
(?m)
必须出现在整个模式的最前面。
理解为
(?m)
开启了一种模式。
有些正则表达式实现还支持
\A
标记字符串的开头,\Z
标记字符串的结尾。但需注意,\A
与\Z
的行为不会因为(?m)
修饰符而改变。
4.子表达式
()
可以划分子表达式对表达式进行分组,可将子表达式作为单一的实体来使用。
(
与)
是元字符,若要表示其本身,需进行转义。
- 可在表达式的某些部分加上括号形成子表达式,以此提高可读性。
- 子表达式支持多重嵌套。
5.反向引用
正则表达式使用\num
来引用之前出现的第num个子表达式(引用之前匹配到的结果)
- 可以将反向引用想象成变量
- 在许多实现里,
\0
可以用来代表整个正则表达式
- 反向引用中编辑或移动子表达式看你会使模式失效,于是一些较新的正则表达式实现还支持“命名捕获”:给某个子表达式起一个唯一的名称
6.替换操作
正则表达式还可以用来完成各种替换。替换操作中需要使用两个正则表达式:一个用来指定搜索模式,另一个用来指定替换模式,而反向引用可以跨模式使用,在第一个模式里匹配的子表达式可以用再第二个模式里。
同一个子表达式可以被引用多次,只需在用到的地方写出其反引用形式即可。
有些正则表达式实现允许使用元字符对字母大小写进行转换。
元字符 | 说明 |
---|---|
\E | 结束\L或\U转换 |
\I | 将下一个字符转换为小写 |
\L | 将\L到\E之间的字符全部转换为小写 |
\u | 把下一个字符转换为大写 |
\U | 把\U到\E之间的字符全部转换为大写 |
7.环视
环视用来匹配文本位置而不会匹配到文本本身(前后查看)。
环视模式中包含一些不用被返回的匹配,这些匹配是为了找出正确的匹配位置,匹配到的字符不会出现在最终的匹配结果中;以实现对匹配结果前后模式的一种约束。
有时使用术语“消耗”来表述“匹配和返回文本的含义”,环视“不消耗所匹配的文本”。
①向前查看
?=
表示向前查看模式,需要匹配的文本跟在=的后面.
表现为字符或子表达式出现在对应文本的最后
任何子表达式都可以转换为向前查看表达式,只要在其之前加上一个
?=
即可,在同一个搜索模式里可以使用多个向前查看表达式,出现的位置没有任何限制。
②向后查看
?<=
操作符表示向后查看
表现为字符或子表达式出现在对应文本的最前。
- 向前查看模式的指定的子表达式长度是可变的,其中可以包含
.
和+
等量词,十分灵活- 而向后查看模式则只能是固定长度。
③否定环视
先前介绍的都属于肯定环视,regex中还有一种否定环视,表示不匹配位于指定字符或子表达式前后的文本,想要使用否定环视操作,的使用!替代=。
种类 | 说明 |
---|---|
(?=) | 肯定视向前查看 |
(?!) | 否定式向前查看 |
(?<=) | 肯定是向后查看 |
(?<!) | 否定式向后查看 |
可以使用向前查看与向后查看包围的字符或子表达式表示匹配位于指定字符/字符串之间的文本。
环视操作允许利用子表达式来指定文本匹配操作发生的位置,但同时不会消耗匹配到的文本(不出现在最终的匹配结果里)。
Ⅳ.嵌入式条件
在表达式的内部嵌入条件处理
1.反向引用条件
定义这种条件的语法式(?(backreference)true)
,其中?
表示其为一个条件,backreference是一个反向引用,仅当反向引用立即出现时,才对表达式求值。
条件还可以有else
形式,其语法为(?(backreference)true|false)
,仅当给定的反向引用不存在时才执行该表达式,此语法接受一个条件和两个分别在符合/不符合该条件时执行的表达式。