正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式通常被用来检索、替换符合模式的文本。正则表达式最早出现在出现在理论计算机科学的自动控制理论中,后来被Unix系统上的编辑器ed使用,并最终发展为grep命令。最后,正则表达式被广泛使用在大多数编程语言中。
基本语法
一个正则表达式通常被称为一个模式,被用来描述、匹配一系列符合某个句法规则的字符串。正则表达式语法包括:
- 字面值,没有任何转义,查找的对象就是其本身。比如正则表达式abc,匹配的结果就是a、b、c三个字母连在一起的字符串。
.
,匹配除换行符外的任意字符。[]
,中括号这种形式被称为字符类。在正则表达式中,一些字符被[]
符号括住,它们表示被括号中属性约束的字符。需要注意两点:- 在字符类中字符的顺序和重复性是没有意义的;
.
在字符类中表示的就是其本身。
-
,为区间符号,表示在给定的范围内取值。[0123456789]
与[0-9]
是相同的,区间的范围应该是有意义的,[a-1]
虽然没有语法错误,但是没有任何意义。区间左右两端对应的是字符,并不是数字,[2-41]
?^
,为取反符号,取反符号必须在[]
中使用,取反符号是将后面的整体作为取反条件的。{}
,为乘法集,以前面的整体作为乘法条件。乘法集区间有如下特点:- 乘法集的“越长越好”属性,对于字符串
aaaabb
,正则表达式a{2,4}
会匹配aaaa
; - 乘法集的“全部获取”属性,对于字符串
aabbaaaab
,正则表达式a{2,4}
会匹配aa
和aaaa
; - 乘法集区间支持开区间,
a{1,}
是合法的。
- 乘法集的“越长越好”属性,对于字符串
?
,为判断符号,同{0,1}
。当该字符紧跟在任何一个其他限制符(*
,+
,?
,{n}
,{n,}
,{n,m}
)后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串oooo
,o+?
将匹配单个o
,而o+
将匹配所有o
。*
,为通配符号,同{0,}
。+
,同{1,}
。|
,为或符号,表示或的关系,abc|edf
表示匹配abc
或者edf
。()
,表示组合,也可以理解为高优先级匹配。\b
,表示单词的边界,也就是指单词和空格间的位置。例如,er\b
可以匹配never
中的er
,但不能匹配verb
中的er
。\B
,匹配非单词边界。er\B
能匹配verb
中的er
,但不能匹配never
中的er
。cx
,匹配由x指明的控制字符。例如,\cM
匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的c字符。\d
,匹配一个数字字符。等价于[0-9]
。\D
,匹配一个非数字字符。等价于[^0-9]
。\f
,匹配一个换页符。等价于\x0c
和\cL
。\n
,匹配一个换行符。等价于\x0a
和\cJ
。\r
,匹配一个回车符。等价于\x0d
和\cM
。\s
,匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]
。\S
,匹配任何非空白字符。等价于[^ \f\n\r\t\v]
。\t
,匹配一个制表符。等价于\x09
和\cI
。\v
,匹配一个垂直制表符。等价于\x0b
和\cK
。\w
,匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
。\W
,匹配任何非单词字符。等价于[^A-Za-z0-9_]
。\xn
,匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,\x41
匹配A
。正则表达式中可以使用ASCII编码。^$
,^
表示行的开头,$
表示行的结尾。\
,转义字符。
高(奇)级(技)语(淫)法(巧)
下面介绍的是一些正则表达式中比较生僻,但是也非常有用的用法。
(pattern)
,匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到。(?:pattern)
,匹配pattern但不获取匹配的子字符串,也就是说这是一个非获取匹配,不存储匹配的子字符串用于向后引用。这在使用或字符(|)
来组合一个模式的各个部分是很有用。例如industr(?:y|ies)
就是一个比industry|industries
更简略的表达式。(?=pattern)
,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,Windows(?=95|98|NT|2000)
能匹配Windows2000
中的Windows
,但不能匹配Windows3.1
中的Windows
。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)
,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如Windows(?!95|98|NT|2000)
能匹配Windows3.1
中的Windows
,但不能匹配Windows2000
中的Windows
。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始(?<=pattern)
,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,(?<=95|98|NT|2000)Windows
能匹配2000Windows
中的Windows
,但不能匹配3.1Windows
中的Windows
。(?<!pattern)
,反向否定预查,与正向否定预查类似,只是方向相反。例如(?<!95|98|NT|2000)Windows
能匹配3.1Windows
中的Windows
,但不能匹配2000Windows
中的Windows
。
贪婪匹配和懒惰匹配
当正则表达式中包含能接受重复的限定符时,在使整个表达式能得到匹配的前提下,通常的行为是匹配尽可能多的字符。以a.*b
为例,它会匹配最长的以a
开始,以b
结束的字符串。如果用它来搜索aabab
的话,会匹配整个字符串,这被称为贪婪匹配。
但是有时我们需要匹配尽可能少的字符-懒惰匹配。贪婪匹配可以转化为懒惰匹配,只需要在表达式中增加一个问号?
。这样.*?
就意味着匹配任意数量的重复,但是在能使匹配成功的前提下使用最少的重复。a.*?b
匹配最短的,以a
开始,以b
结束的字符串。如果把它用于匹配aabab
的话,会匹配aab
和ab
。
参考资料
声明:欢迎转载,请注明出处。