一 . 使用元字符
1. 对特殊字符进行转义
元字符是一些在正则表达式里有着特殊含义的字符,所以这些字符就无法用来代表它们本身。任何一个元字符都可以通过给它加上一个反斜杠字符/ 作为前缀的办法来转义。
2. 匹配空白字符
元字符大致可以分为两种:一种是用来匹配文本的(比如. ),另一种是正则表达式的语法要求的(比如[ 和] )。
在进行正则表达式搜索的时候,我们经常会遇到需要对原始文本里的非打印空白字符进行匹配,或者我们需要把换行符找出来,这类字符很难被直接输入到一个正则表达式中,但我们可以使用下列的特殊字符来输入:
空白元字符
元字符 说明
[/b] 回退(并删除)一个字符( backspace 键)
/f 换页符
/n 换行符
/r 回车符
/t 制表符( Tab 键)
/v 垂直制表符
注: /r/n 是 windows 所使用的文本行结束标签。 Unix 和 Linux 系统只使用一个换行符结束一个文本行;换句话说,在 Unix/Linux 系统上匹配空白行只使用 /n/n 即可,不需要加上 /r 。
3. 匹配特定的字符类别
一些常用的字符集合可以用特殊的元字符来代替。这些元字符匹配的是某一类别的字符(术语称之为“字符类”)。
( 1 )匹配数字
数字元字符
元字符 说明
/d 任何一个数字字符(等价于[ 0-9 ])
/D 任何一个非数字字符(等价于[ ^0-9 ])
例子:
文本
xyf[1]
xyf[5]
xyf[a]
正则表达式: xyf/[/d/]
结果:
Matches Found: 2
Match | Position | Length |
---|---|---|
xyf[1] | 0 | 6 |
xyf[5] | 7 | 6 |
( 2 )匹配字母和数字(与非字母和数字)
字母数字元字符
元字符 说明
/w 任何一个字母数字字符(大小写均可)或下划线字符(等价于[ a-zA-Z0-9_ ])
/W 任何一个非字母数字和非下划线字符 ( 等价于 [^a-zA-Z0-9_])
( 3 )匹配空白字符(非空白字符)
空白字符元字符
元字符 说明
/s 任何一个空白字符(等价于 [/f/n/r/t/v] )
/S 任何一个非空白字符(等价于 [^/f/n/r/t/v] )
注意:用来匹配退格字符的 [/b] 元字符是一个特例:它不在元字符 /s 的覆盖范围内,当然也没排除在类元字符 /S 的覆盖范围外。
( 4 )匹配十六进制或八进制
使用十六进制值
在正则表达式里,十六进制数值要用前缀 /x 来给出。比如, /x0A 对应于 ASCII 字符 10 (换行符),其效果等价于 /n 。
使用八进制值
在正则表达式中,八进制数值要用前缀 /0 来给出,数值本身可以是两位或者三位。比如 /011 对应于 ASCII 字符 9 (制表符),其效果等价于 /t 。
4. 使用 POSIX 字符类
(省略)
二 . 重复匹配
1. 匹配一个或多个字符
要想匹配同一个字符或字符集合的多次重复,只要简单地给这个字符或字符集合加上一个 + 字符作为后缀就行了。比如, a 匹配 a 本身, a+ 将匹配一个或多个连续出现的 a 。类似地, [0-9] 匹配任意单个数字, [0-9]+ 将匹配一个或多个连续的数字。
例子:
文本
fnoiaqowoe qwjeqw
xyf@shu.edu.cn aoidahoiqw
daidoqwideqw
正则表达式: /w+@[/w.]+/w
结果:
Matches Found: 1
Match | Position | Length |
---|---|---|
xyf@shu.edu.cn | 18 | 14 |
2. 匹配零个或多个字符
+ 匹配一个或者多个字符。但不匹配零个字符。如果你想匹配一个可有可无的字符,可用元字符*
3. 匹配零个或一个字符
元字符 ? 只能匹配一个字符(或字符集合)的零次或一次出现,最多不超过一次。如果需要在一段文本里匹配某个特定的字符(或字符集合)而该字符可能出现,也可能不出现,?无疑是最佳的选择。
例子:
文本
welcome to http://www.shu.edu.cn/ and https://www.xiayf.org/
正则表达式: https?//[/w.]+?/
结果:
Matches Found: 2
Match | Position | Length |
---|---|---|
http://www.shu.edu.cn/ | 11 | 22 |
https://www.xiayf.org/ | 38 | 22 |
4. 匹配的重复次数
上次几种正则表达式的缺陷:
+和*匹配的字符个数没有上限。我们无法为它们将匹配的字符个数设置一个最大值。
+,*和?至少匹配零个或者一个字符。我们无法为它们将匹配的字符个数另行设定一个最小值。
如果只使用+和*,我们无法把它们将匹配的字符个数设定为一个精确的数字。
解决方法:重复次数用{和}来给出---把数值写在它们中间。
( 1 )为重复匹配次数设定一个精确的值
例子:
文本
一段文本中有一个 ipv6 地址为:
daiodhqoidqw 1080:0000:0000:0000:0008:0800:200C:417Adajd9w0quednaldjojdi
正则表达式:(/w{4}:){7}(/w{4})
结果
Matches Found: 1
Match | Position | Length |
---|---|---|
1080:0000:0000:0000:0008:0800:200C:417A | 12 | 39 |
(2 )为重复匹配次数设定一个区间
也就是为重复匹配次数设定一个最大值和最小值。
例子
文本:
4/8/03
10-6-2004
2/2/2
01-01-01
正则表达式: /d{1,2}[-//]/d{1,2}[-//]/d{2,4}
结果:
Matches Found: 3
Match | Position | Length |
---|---|---|
4/8/03 | 0 | 6 |
10-6-2004 | 7 | 9 |
01-01-01 | 23 | 8 |
如果想匹配“至少重复多少次”,也即最少要重复匹配多少次,则可把区间格式里的第二个数字省略。但 , 不可省略。
例子
文本和上例相同
正则表达式: /d{1,2}[-//]/d{2,}[-//]/d{2,4}
结果:
Matches Found: 1
Match | Position | Length |
---|---|---|
01-01-01 | 23 | 8 |
5. 防止过度匹配
?只能匹配零个或一个字符,{ n }和{ m,n }也有一个重复次数的上限;换句话说,这几种语法所定义的“重复次数”都是有限的,但是上述其他几种重复匹配语法在重复次数方面没有上限,而这样做有时会导致过度匹配的现象。
例子:
文本
this offer is not available to customers
living in <B>AK</B> and <B>HI</B>
说明:我们希望把两个 <B> 和 </B> 之间的内容取出来,但是不要其中的 and
正则表达式: <[Bb]>.*</[Bb]>
结果:
Matches Found: 1
Match | Position | Length |
---|---|---|
AK and HI | 51 | 23 |
显然结果不符合我们的预期。为什么会这样呢?因为*和+都是所谓的“贪婪型”元字符,它们在进行匹配时的行为模式是多多益善而不是适可而止。那怎么办呢?答案是使用这些元字符的“懒惰型”版本。
常用的贪婪型元字符和它们的懒惰型元字符
贪婪型元字符 懒惰型元字符
* *?
+ +?
{ n, } { n, }?
则上例的正则表达式可改为: <[Bb]>.* ? </[Bb]> 即可。
(未完待续)