- 浏览: 1584333 次
- 性别:
文章分类
- 全部博客 (2929)
- 非技术 (18)
- Eclipse (11)
- JAVA (31)
- 正则表达式 (0)
- J2EE (4)
- DOS命令 (2)
- WEB前端 (52)
- JavaScript (69)
- 数据库 (8)
- 设计模式 (0)
- JFreechart (1)
- 操作系统 (1)
- 互联网 (10)
- EasyMock (1)
- jQuery (5)
- Struts2 (12)
- Spring (24)
- 浏览器 (16)
- OGNL (1)
- WebService (12)
- OSGi (14)
- 软件 (10)
- Tomcat (2)
- Ext (3)
- SiteMesh (2)
- 开源软件 (2)
- Hibernate (2)
- Quartz (6)
- iBatis (2)
最新评论
正则表达式基础
前言
正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。
索引
1.引子
目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux,Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。
正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。
例子:^.+@.+//..+$
这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。
注意:这里的第7部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。
2.正则表达式的历史
正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。WarrenMcCulloch和WalterPitts这两位神经生理学家研究出一种数学方式来描述这些神经网络。
1956年,一位叫StephenKleene的数学家在McCulloch和Pitts早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。
随后,发现可以将这一工作应用于使用KenThompson的计算搜索算法的一些早期研究,KenThompson是Unix的主要发明人。正则表达式的第一个实用应用程序就是Unix中的qed编辑器。
如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。
3.正则表达式定义
正则表达式(regularexpression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
列目录时, dir*.txt或ls*.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。
正则表达式是由普通字符(例如字符a到z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
3.1普通字符
由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。
3.2非打印字符
字符含义
/cx匹配由x指明的控制字符。例如,/cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的'c'字符。
/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。
3.3特殊字符
所谓特殊字符,就是一些有特殊含义的字符,如上面说的"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个/。ls/*.txt。正则表达式有以下特殊字符。
特别字符说明
$匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则$也匹配'/n'或'/r'。要匹配$字符本身,请使用/$。
()标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用/(和/)。
*匹配前面的子表达式零次或多次。要匹配*字符,请使用/*。
+匹配前面的子表达式一次或多次。要匹配+字符,请使用/+。
.匹配除换行符/n之外的任何单字符。要匹配.,请使用/。
[标记一个中括号表达式的开始。要匹配[,请使用/[。
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配?字符,请使用/?。
/将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如,'n'匹配字符'n'。'/n'匹配换行符。序列'//'匹配"/",而'/('则匹配"("。
^匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配^字符本身,请使用/^。
{标记限定符表达式的开始。要匹配{,请使用/{。
|指明两项之间的一个选择。要匹配|,请使用/|。
构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
3.4限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。
*、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
正则表达式的限定符有:
字符描述
*匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,'o{2}'不能匹配"Bob"中的'o',但是能匹配"food"中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,'o{2,}'不能匹配"Bob"中的'o',但能匹配"foooood"中的所有o。'o{1,}'等价于'o+'。'o{0,}'则等价于'o*'。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o。'o{0,1}'等价于'o?'。请注意在逗号和两个数之间不能有空格。
3.5定位符
用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,/b描述单词的前或后边界,/B表示非单词边界。不能对定位符使用限定符。
3.6选择
用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。
其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
3.7后向引用
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从1开始,连续编号直至最大99个子表达式。每个缓冲区都可以使用'/n'访问,其中n为一个标识特定缓冲区的一位或两位十进制数。
可以使用非捕获元字符'?:','?=',or'?!'来忽略对相关匹配的保存。
4.各种操作符的运算优先级
相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:
操作符描述
/转义符
(),(?:),(?=),[]圆括号和方括号
*,+,?,{n},{n,},{n,m}限定符
^,$,/anymetacharacter位置和顺序
|“或”操作
5.全部符号解释
字符描述
/将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,'n'匹配字符"n"。'/n'匹配一个换行符。序列'//'匹配"/"而"/("则匹配"("。
^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配'/n'或'/r'之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配'/n'或'/r'之前的位置。
*匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,'o{2}'不能匹配"Bob"中的'o',但是能匹配"food"中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,'o{2,}'不能匹配"Bob"中的'o',但能匹配"foooood"中的所有o。'o{1,}'等价于'o+'。'o{0,}'则等价于'o*'。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o。'o{0,1}'等价于'o?'。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串"oooo",'o+?'将匹配单个"o",而'o+'将匹配所有'o'。
.匹配除"/n"之外的任何单个字符。要匹配包括'/n'在内的任何字符,请使用象'[./n]'的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用'/('或'/)'。
(?: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"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y匹配x或y。例如,'z|food'能匹配"z"或"food"。'(z|f)ood'则匹配"zood"或"food"。
[xyz]字符集合。匹配所包含的任意一个字符。例如,'[abc]'可以匹配"plain"中的'a'。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,'[^abc]'可以匹配"plain"中的'p'。
[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]'可以匹配'a'到'z'范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]'可以匹配任何不在'a'到'z'范围内的任意字符。
/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"。'/x041'则等价于'/x04'&"1"。正则表达式中可以使用ASCII编码。.
/num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,'(.)/1'匹配两个连续的相同字符。
/n标识一个八进制转义值或一个向后引用。如果/n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
/nm标识一个八进制转义值或一个向后引用。如果/nm之前至少有nm个获得子表达式,则nm为向后引用。如果/nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则/nm将匹配八进制转义值nm。
/nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
/un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,/u00A9匹配版权符号(?)。
6.部分例子
正则表达式说明
//b([a-z]+)/1/b/gi一个单词连续出现的位置
/(/w+):////([^/:]+)(:/d*)?([^#]*)/将一个URL解析为协议、域、端口及相对路径
/^(?:Chapter|Section)[1-9][0-9]{0,1}$/定位章节的位置
/[-a-z]/A至z共26个字母再加一个-号。
/ter/b/可匹配chapter,而不能terminal
//Bapt/可匹配chapter,而不能aptitude
/Windows(?=95|98|NT)/可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。
7.正则表达式匹配规则
7.1基本模式匹配
一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:
^once
这个模式包含一个特殊的字符^,表示该模式只匹配那些以once开头的字符串。例如该模式与字符串"onceuponatime"匹配,与"ThereoncewasamanfromNewYork"不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。
bucket$
这个模式与"Whokeptallofthiscashinabucket"匹配,与"buckets"不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:
^bucket$
只匹配字符串"bucket"。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式
once
与字符串
ThereoncewasamanfromNewYork
Whokeptallofhiscashinabucket.
是匹配的。
在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠(/)打头。制表符的转义序列是:/t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:
^/t
类似的,用/n表示“新行”,/r表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用//表示,句号.用/.表示,以此类推。
7.2字符簇
在INTERNET的程序中,正规表达式通常用来验证用户的输入。当用户提交一个FORM以后,要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。
所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:
[AaEeIiOoUu]
这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:
[a-z]//匹配所有的小写字母
[A-Z]//匹配所有的大写字母
[a-zA-Z]//匹配所有的字母
[0-9]//匹配所有的数字
[0-9/./-]//匹配所有的数字,句号和减号
[/f/r/t/n]//匹配所有的白字符
同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3"或"b52"的话,用这个模式:
^[a-z][0-9]$
尽管[a-z]代表26个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。
前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:
^[^0-9][0-9]$
这个模式与"&5"、"g7"及"-2"是匹配的,但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子:
[^a-z]//除了小写字母以外的所有字符
[^/////^]//除了(/)(/)(^)之外的所有字符
[^/"/']//除了双引号(")和单引号(')之外的所有字符
特殊字符"."(点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字5结尾和以其他非“新行”字符开头的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。
PHP的正规表达式有一些内置的通用字符簇,列表如下:
字符簇含义
[[:alpha:]]任何字母
[[:digit:]]任何数字
[[:alnum:]]任何字母和数字
[[:space:]]任何白字符
[[:upper:]]任何大写字母
[[:lower:]]任何小写字母
[[:punct:]]任何标点符号
[[:xdigit:]]任何16进制的数字,相当于[0-9a-fA-F]
7.3确定重复出现
到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。
字符簇含义
^[a-zA-Z_]$所有的字母和下划线
^[[:alpha:]]{3}$所有的3个字母的单词
^a$字母a
^a{4}$aaaa
^a{2,4}$aa,aaa或aaaa
^a{1,3}$a,aa或aaa
^a{2,}$包含多于两个a的字符串
^a{2,}如:aardvark和aaab,但apple不行
a{2,}如:baad和aaa,但Nantucket不行
/t{2}两个制表符
.{2}所有的两个字符
这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现x次”;一个数字加逗号,{x,}的意思是“前面的内容出现x或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现x次,但不超过y次”。我们可以把模式扩展到更多的单词或数字:
^[a-zA-Z0-9_]{1,}$//所有包含一个以上的字母、数字或下划线的字符串
^[0-9]{1,}$//所有的正数
^/-{0,1}[0-9]{1,}$//所有的整数
^/-{0,1}[0-9]{0,}/.{0,1}[0-9]{0,}$//所有的小数
最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(/-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(/.{0,1})再跟上0个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。
特殊字符"?"与{0,1}是相等的,它们都代表着:“0个或1个前面的内容”或“前面的内容是可选的”。所以刚才的例子可以简化为:
^/-?[0-9]{0,}/.?[0-9]{0,}$
特殊字符"*"与{0,}是相等的,它们都代表着“0个或多个前面的内容”。最后,字符"+"与{1,}是相等的,表示“1个或多个前面的内容”,所以上面的4个例子可以写成:
^[a-zA-Z0-9_]+$//所有包含一个以上的字母、数字或下划线的字符串
^[0-9]+$//所有的正数
^/-?[0-9]+$//所有的整数
^/-?[0-9]*/.?[0-9]*$//所有的小数
当然这并不能从技术上降低正规表达式的复杂性,但可以使它们更容易阅读。
如果我们问那些UNIX系统的爱好者他们最喜欢什么,答案除了稳定的系统和可以远程启动之外,十有八九的人会提到正则表达式;如果我们再问他们最头痛的是什么,可能除了复杂的进程控制和安装过程之外,还会是正则表达式。那么正则表达式到底是什么?如何才能真正的掌握正则表达式并正确的加以灵活运用?本文将就此展开介绍,希望能够对那些渴望了解和掌握正则表达式的读者有所助益。
入门简介
简单的说,正则表达式是一种可以用于模式匹配和替换的强有力的工具。我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或sedshell程序等。此外,象Javascript这种客户端的脚本语言也提供了对正则表达式的支持。由此可见,正则表达式已经超出了某种语言或某个系统的局限,成为人们广为接受的概念和功能。
正则表达式可以让用户通过使用一系列的特殊字符构建匹配模式,然后把匹配模式与数据文件、程序输入以及WEB页面的表单输入等目标对象进行比较,根据比较对象中是否包含匹配模式,执行相应的程序。
举例来说,正则表达式的一个最为普遍的应用就是用于验证用户在线输入的邮件地址的格式是否正确。如果通过正则表达式验证用户邮件地址的格式正确,用户所填写的表单信息将会被正常处理;反之,如果用户输入的邮件地址与正则表达的模式不匹配,将会弹出提示信息,要求用户重新输入正确的邮件地址。由此可见正则表达式在WEB应用的逻辑判断中具有举足轻重的作用。
基本语法
在对正则表达式的功能和作用有了初步的了解之后,我们就来具体看一下正则表达式的语法格式。
正则表达式的形式一般如下:
/love/
其中位于“/”定界符之间的部分就是将要在目标对象中进行匹配的模式。用户只要把希望查找匹配对象的模式内容放入“/”定界符之间即可。为了能够使用户更加灵活的定制模式内容,正则表达式提供了专门的“元字符”。所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。
较为常用的元字符包括:“+”,“*”,以及“?”。其中,“+”元字符规定其前导字符必须在目标对象中连续出现一次或多次,“*”元字符规定其前导字符必须在目标对象中出现零次或连续多次,而“?”元字符规定其前导对象必须在目标对象中连续出现零次或一次。
下面,就让我们来看一下正则表达式元字符的具体应用。
/fo+/
因为上述正则表达式中包含“+”元字符,表示可以与目标对象中的“fool”,“fo”,或者“football”等在字母f后面连续出现一个或多个字母o的字符串相匹配。
/eg*/
因为上述正则表达式中包含“*”元字符,表示可以与目标对象中的“easy”,“ego”,或者“egg”等在字母e后面连续出现零个或多个字母g的字符串相匹配。
/Wil?/
因为上述正则表达式中包含“?”元字符,表示可以与目标对象中的“Win”,或者“Wilson”,等在字母i后面连续出现零个或一个字母l的字符串相匹配。
除了元字符之外,用户还可以精确指定模式在匹配对象中出现的频率。例如,
/jim{2,6}/
上述正则表达式规定字符m可以在匹配对象中连续出现2-6次,因此,上述正则表达式可以同jimmy或jimmmmmy等字符串相匹配。
在对如何使用正则表达式有了初步了解之后,我们来看一下其它几个重要的元字符的使用方式。
/s:用于匹配单个空格符,包括tab键和换行符;
/S:用于匹配除单个空格符之外的所有字符;
/d:用于匹配从0到9的数字;
/w:用于匹配字母,数字或下划线字符;
/W:用于匹配所有与/w不匹配的字符;
.:用于匹配除换行符之外的所有字符。
(说明:我们可以把/s和/S以及/w和/W看作互为逆运算)
下面,我们就通过实例看一下如何在正则表达式中使用上述元字符。
//s+/
上述正则表达式可以用于匹配目标对象中的一个或多个空格字符。
//d000/
如果我们手中有一份复杂的财务报表,那么我们可以通过上述正则表达式轻而易举的查找到所有总额达千元的款项。
除了我们以上所介绍的元字符之外,正则表达式中还具有另外一种较为独特的专用字符,即定位符。定位符用于规定匹配模式在目标对象中的出现位置。
较为常用的定位符包括:“^”,“$”,“/b”以及“/B”。其中,“^”定位符规定匹配模式必须出现在目标字符串的开头,“$”定位符规定匹配模式必须出现在目标对象的结尾,/b定位符规定匹配模式必须出现在目标字符串的开头或结尾的两个边界之一,而“/B”定位符则规定匹配对象必须位于目标字符串的开头和结尾两个边界之内,即匹配对象既不能作为目标字符串的开头,也不能作为目标字符串的结尾。同样,我们也可以把“^”和“$”以及“/b”和“/B”看作是互为逆运算的两组定位符。举例来说:
/^hell/
因为上述正则表达式中包含“^”定位符,所以可以与目标对象中以“hell”,“hello”或“hellhound”开头的字符串相匹配。
/ar$/
因为上述正则表达式中包含“$”定位符,所以可以与目标对象中以“car”,“bar”或“ar”结尾的字符串相匹配。
//bbom/
因为上述正则表达式模式以“/b”定位符开头,所以可以与目标对象中以“bomb”,或“bom”开头的字符串相匹配。
/man/b/
因为上述正则表达式模式以“/b”定位符结尾,所以可以与目标对象中以“human”,“woman”或“man”结尾的字符串相匹配。
为了能够方便用户更加灵活的设定匹配模式,正则表达式允许使用者在匹配模式中指定某一个范围而不局限于具体的字符。例如:
/[A-Z]/
上述正则表达式将会与从A到Z范围内任何一个大写字母相匹配。
/[a-z]/
上述正则表达式将会与从a到z范围内任何一个小写字母相匹配。
/[0-9]/
上述正则表达式将会与从0到9范围内任何一个数字相匹配。
/([a-z][A-Z][0-9])+/
上述正则表达式将会与任何由字母和数字组成的字符串,如“aB0”等相匹配。这里需要提醒用户注意的一点就是可以在正则表达式中使用“()”把字符串组合在一起。“()”符号包含的内容必须同时出现在目标对象中。因此,上述正则表达式将无法与诸如“abc”等的字符串匹配,因为“abc”中的最后一个字符为字母而非数字。
如果我们希望在正则表达式中实现类似编程逻辑中的“或”运算,在多个不同的模式中任选一个进行匹配的话,可以使用管道符“|”。例如:
/to|too|2/
上述正则表达式将会与目标对象中的“to”,“too”,或“2”相匹配。
正则表达式中还有一个较为常用的运算符,即否定符“[^]”。与我们前文所介绍的定位符“^”不同,否定符“[^]”规定目标对象中不能存在模式中所规定的字符串。例如:
/[^A-C]/
上述字符串将会与目标对象中除A,B,和C之外的任何字符相匹配。一般来说,当“^”出现在“[]”内时就被视做否定运算符;而当“^”位于“[]”之外,或没有“[]”时,则应当被视做定位符。
最后,当用户需要在正则表达式的模式中加入元字符,并查找其匹配对象时,可以使用转义符“/”。例如:
/Th/*/
上述正则表达式将会与目标对象中的“Th*”而非“The”等相匹配。
正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。
索引
1.引子
目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux,Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。
正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。
例子:^.+@.+//..+$
这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。
注意:这里的第7部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。
2.正则表达式的历史
正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。WarrenMcCulloch和WalterPitts这两位神经生理学家研究出一种数学方式来描述这些神经网络。
1956年,一位叫StephenKleene的数学家在McCulloch和Pitts早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。
随后,发现可以将这一工作应用于使用KenThompson的计算搜索算法的一些早期研究,KenThompson是Unix的主要发明人。正则表达式的第一个实用应用程序就是Unix中的qed编辑器。
如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。
3.正则表达式定义
正则表达式(regularexpression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
列目录时, dir*.txt或ls*.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。
正则表达式是由普通字符(例如字符a到z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
3.1普通字符
由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。
3.2非打印字符
字符含义
/cx匹配由x指明的控制字符。例如,/cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的'c'字符。
/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。
3.3特殊字符
所谓特殊字符,就是一些有特殊含义的字符,如上面说的"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个/。ls/*.txt。正则表达式有以下特殊字符。
特别字符说明
$匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则$也匹配'/n'或'/r'。要匹配$字符本身,请使用/$。
()标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用/(和/)。
*匹配前面的子表达式零次或多次。要匹配*字符,请使用/*。
+匹配前面的子表达式一次或多次。要匹配+字符,请使用/+。
.匹配除换行符/n之外的任何单字符。要匹配.,请使用/。
[标记一个中括号表达式的开始。要匹配[,请使用/[。
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配?字符,请使用/?。
/将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如,'n'匹配字符'n'。'/n'匹配换行符。序列'//'匹配"/",而'/('则匹配"("。
^匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配^字符本身,请使用/^。
{标记限定符表达式的开始。要匹配{,请使用/{。
|指明两项之间的一个选择。要匹配|,请使用/|。
构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
3.4限定符
限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。
*、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
正则表达式的限定符有:
字符描述
*匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,'o{2}'不能匹配"Bob"中的'o',但是能匹配"food"中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,'o{2,}'不能匹配"Bob"中的'o',但能匹配"foooood"中的所有o。'o{1,}'等价于'o+'。'o{0,}'则等价于'o*'。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o。'o{0,1}'等价于'o?'。请注意在逗号和两个数之间不能有空格。
3.5定位符
用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,/b描述单词的前或后边界,/B表示非单词边界。不能对定位符使用限定符。
3.6选择
用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。
其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
3.7后向引用
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从1开始,连续编号直至最大99个子表达式。每个缓冲区都可以使用'/n'访问,其中n为一个标识特定缓冲区的一位或两位十进制数。
可以使用非捕获元字符'?:','?=',or'?!'来忽略对相关匹配的保存。
4.各种操作符的运算优先级
相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:
操作符描述
/转义符
(),(?:),(?=),[]圆括号和方括号
*,+,?,{n},{n,},{n,m}限定符
^,$,/anymetacharacter位置和顺序
|“或”操作
5.全部符号解释
字符描述
/将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,'n'匹配字符"n"。'/n'匹配一个换行符。序列'//'匹配"/"而"/("则匹配"("。
^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配'/n'或'/r'之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配'/n'或'/r'之前的位置。
*匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"do"或"does"中的"do"。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,'o{2}'不能匹配"Bob"中的'o',但是能匹配"food"中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,'o{2,}'不能匹配"Bob"中的'o',但能匹配"foooood"中的所有o。'o{1,}'等价于'o+'。'o{0,}'则等价于'o*'。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o。'o{0,1}'等价于'o?'。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串"oooo",'o+?'将匹配单个"o",而'o+'将匹配所有'o'。
.匹配除"/n"之外的任何单个字符。要匹配包括'/n'在内的任何字符,请使用象'[./n]'的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用'/('或'/)'。
(?: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"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y匹配x或y。例如,'z|food'能匹配"z"或"food"。'(z|f)ood'则匹配"zood"或"food"。
[xyz]字符集合。匹配所包含的任意一个字符。例如,'[abc]'可以匹配"plain"中的'a'。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,'[^abc]'可以匹配"plain"中的'p'。
[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]'可以匹配'a'到'z'范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]'可以匹配任何不在'a'到'z'范围内的任意字符。
/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"。'/x041'则等价于'/x04'&"1"。正则表达式中可以使用ASCII编码。.
/num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,'(.)/1'匹配两个连续的相同字符。
/n标识一个八进制转义值或一个向后引用。如果/n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
/nm标识一个八进制转义值或一个向后引用。如果/nm之前至少有nm个获得子表达式,则nm为向后引用。如果/nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则/nm将匹配八进制转义值nm。
/nml如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
/un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,/u00A9匹配版权符号(?)。
6.部分例子
正则表达式说明
//b([a-z]+)/1/b/gi一个单词连续出现的位置
/(/w+):////([^/:]+)(:/d*)?([^#]*)/将一个URL解析为协议、域、端口及相对路径
/^(?:Chapter|Section)[1-9][0-9]{0,1}$/定位章节的位置
/[-a-z]/A至z共26个字母再加一个-号。
/ter/b/可匹配chapter,而不能terminal
//Bapt/可匹配chapter,而不能aptitude
/Windows(?=95|98|NT)/可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。
7.正则表达式匹配规则
7.1基本模式匹配
一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:
^once
这个模式包含一个特殊的字符^,表示该模式只匹配那些以once开头的字符串。例如该模式与字符串"onceuponatime"匹配,与"ThereoncewasamanfromNewYork"不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。
bucket$
这个模式与"Whokeptallofthiscashinabucket"匹配,与"buckets"不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:
^bucket$
只匹配字符串"bucket"。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式
once
与字符串
ThereoncewasamanfromNewYork
Whokeptallofhiscashinabucket.
是匹配的。
在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠(/)打头。制表符的转义序列是:/t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:
^/t
类似的,用/n表示“新行”,/r表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用//表示,句号.用/.表示,以此类推。
7.2字符簇
在INTERNET的程序中,正规表达式通常用来验证用户的输入。当用户提交一个FORM以后,要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。
所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:
[AaEeIiOoUu]
这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:
[a-z]//匹配所有的小写字母
[A-Z]//匹配所有的大写字母
[a-zA-Z]//匹配所有的字母
[0-9]//匹配所有的数字
[0-9/./-]//匹配所有的数字,句号和减号
[/f/r/t/n]//匹配所有的白字符
同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3"或"b52"的话,用这个模式:
^[a-z][0-9]$
尽管[a-z]代表26个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。
前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:
^[^0-9][0-9]$
这个模式与"&5"、"g7"及"-2"是匹配的,但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子:
[^a-z]//除了小写字母以外的所有字符
[^/////^]//除了(/)(/)(^)之外的所有字符
[^/"/']//除了双引号(")和单引号(')之外的所有字符
特殊字符"."(点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字5结尾和以其他非“新行”字符开头的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。
PHP的正规表达式有一些内置的通用字符簇,列表如下:
字符簇含义
[[:alpha:]]任何字母
[[:digit:]]任何数字
[[:alnum:]]任何字母和数字
[[:space:]]任何白字符
[[:upper:]]任何大写字母
[[:lower:]]任何小写字母
[[:punct:]]任何标点符号
[[:xdigit:]]任何16进制的数字,相当于[0-9a-fA-F]
7.3确定重复出现
到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。
字符簇含义
^[a-zA-Z_]$所有的字母和下划线
^[[:alpha:]]{3}$所有的3个字母的单词
^a$字母a
^a{4}$aaaa
^a{2,4}$aa,aaa或aaaa
^a{1,3}$a,aa或aaa
^a{2,}$包含多于两个a的字符串
^a{2,}如:aardvark和aaab,但apple不行
a{2,}如:baad和aaa,但Nantucket不行
/t{2}两个制表符
.{2}所有的两个字符
这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现x次”;一个数字加逗号,{x,}的意思是“前面的内容出现x或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现x次,但不超过y次”。我们可以把模式扩展到更多的单词或数字:
^[a-zA-Z0-9_]{1,}$//所有包含一个以上的字母、数字或下划线的字符串
^[0-9]{1,}$//所有的正数
^/-{0,1}[0-9]{1,}$//所有的整数
^/-{0,1}[0-9]{0,}/.{0,1}[0-9]{0,}$//所有的小数
最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(/-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(/.{0,1})再跟上0个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。
特殊字符"?"与{0,1}是相等的,它们都代表着:“0个或1个前面的内容”或“前面的内容是可选的”。所以刚才的例子可以简化为:
^/-?[0-9]{0,}/.?[0-9]{0,}$
特殊字符"*"与{0,}是相等的,它们都代表着“0个或多个前面的内容”。最后,字符"+"与{1,}是相等的,表示“1个或多个前面的内容”,所以上面的4个例子可以写成:
^[a-zA-Z0-9_]+$//所有包含一个以上的字母、数字或下划线的字符串
^[0-9]+$//所有的正数
^/-?[0-9]+$//所有的整数
^/-?[0-9]*/.?[0-9]*$//所有的小数
当然这并不能从技术上降低正规表达式的复杂性,但可以使它们更容易阅读。
如果我们问那些UNIX系统的爱好者他们最喜欢什么,答案除了稳定的系统和可以远程启动之外,十有八九的人会提到正则表达式;如果我们再问他们最头痛的是什么,可能除了复杂的进程控制和安装过程之外,还会是正则表达式。那么正则表达式到底是什么?如何才能真正的掌握正则表达式并正确的加以灵活运用?本文将就此展开介绍,希望能够对那些渴望了解和掌握正则表达式的读者有所助益。
入门简介
简单的说,正则表达式是一种可以用于模式匹配和替换的强有力的工具。我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或sedshell程序等。此外,象Javascript这种客户端的脚本语言也提供了对正则表达式的支持。由此可见,正则表达式已经超出了某种语言或某个系统的局限,成为人们广为接受的概念和功能。
正则表达式可以让用户通过使用一系列的特殊字符构建匹配模式,然后把匹配模式与数据文件、程序输入以及WEB页面的表单输入等目标对象进行比较,根据比较对象中是否包含匹配模式,执行相应的程序。
举例来说,正则表达式的一个最为普遍的应用就是用于验证用户在线输入的邮件地址的格式是否正确。如果通过正则表达式验证用户邮件地址的格式正确,用户所填写的表单信息将会被正常处理;反之,如果用户输入的邮件地址与正则表达的模式不匹配,将会弹出提示信息,要求用户重新输入正确的邮件地址。由此可见正则表达式在WEB应用的逻辑判断中具有举足轻重的作用。
基本语法
在对正则表达式的功能和作用有了初步的了解之后,我们就来具体看一下正则表达式的语法格式。
正则表达式的形式一般如下:
/love/
其中位于“/”定界符之间的部分就是将要在目标对象中进行匹配的模式。用户只要把希望查找匹配对象的模式内容放入“/”定界符之间即可。为了能够使用户更加灵活的定制模式内容,正则表达式提供了专门的“元字符”。所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。
较为常用的元字符包括:“+”,“*”,以及“?”。其中,“+”元字符规定其前导字符必须在目标对象中连续出现一次或多次,“*”元字符规定其前导字符必须在目标对象中出现零次或连续多次,而“?”元字符规定其前导对象必须在目标对象中连续出现零次或一次。
下面,就让我们来看一下正则表达式元字符的具体应用。
/fo+/
因为上述正则表达式中包含“+”元字符,表示可以与目标对象中的“fool”,“fo”,或者“football”等在字母f后面连续出现一个或多个字母o的字符串相匹配。
/eg*/
因为上述正则表达式中包含“*”元字符,表示可以与目标对象中的“easy”,“ego”,或者“egg”等在字母e后面连续出现零个或多个字母g的字符串相匹配。
/Wil?/
因为上述正则表达式中包含“?”元字符,表示可以与目标对象中的“Win”,或者“Wilson”,等在字母i后面连续出现零个或一个字母l的字符串相匹配。
除了元字符之外,用户还可以精确指定模式在匹配对象中出现的频率。例如,
/jim{2,6}/
上述正则表达式规定字符m可以在匹配对象中连续出现2-6次,因此,上述正则表达式可以同jimmy或jimmmmmy等字符串相匹配。
在对如何使用正则表达式有了初步了解之后,我们来看一下其它几个重要的元字符的使用方式。
/s:用于匹配单个空格符,包括tab键和换行符;
/S:用于匹配除单个空格符之外的所有字符;
/d:用于匹配从0到9的数字;
/w:用于匹配字母,数字或下划线字符;
/W:用于匹配所有与/w不匹配的字符;
.:用于匹配除换行符之外的所有字符。
(说明:我们可以把/s和/S以及/w和/W看作互为逆运算)
下面,我们就通过实例看一下如何在正则表达式中使用上述元字符。
//s+/
上述正则表达式可以用于匹配目标对象中的一个或多个空格字符。
//d000/
如果我们手中有一份复杂的财务报表,那么我们可以通过上述正则表达式轻而易举的查找到所有总额达千元的款项。
除了我们以上所介绍的元字符之外,正则表达式中还具有另外一种较为独特的专用字符,即定位符。定位符用于规定匹配模式在目标对象中的出现位置。
较为常用的定位符包括:“^”,“$”,“/b”以及“/B”。其中,“^”定位符规定匹配模式必须出现在目标字符串的开头,“$”定位符规定匹配模式必须出现在目标对象的结尾,/b定位符规定匹配模式必须出现在目标字符串的开头或结尾的两个边界之一,而“/B”定位符则规定匹配对象必须位于目标字符串的开头和结尾两个边界之内,即匹配对象既不能作为目标字符串的开头,也不能作为目标字符串的结尾。同样,我们也可以把“^”和“$”以及“/b”和“/B”看作是互为逆运算的两组定位符。举例来说:
/^hell/
因为上述正则表达式中包含“^”定位符,所以可以与目标对象中以“hell”,“hello”或“hellhound”开头的字符串相匹配。
/ar$/
因为上述正则表达式中包含“$”定位符,所以可以与目标对象中以“car”,“bar”或“ar”结尾的字符串相匹配。
//bbom/
因为上述正则表达式模式以“/b”定位符开头,所以可以与目标对象中以“bomb”,或“bom”开头的字符串相匹配。
/man/b/
因为上述正则表达式模式以“/b”定位符结尾,所以可以与目标对象中以“human”,“woman”或“man”结尾的字符串相匹配。
为了能够方便用户更加灵活的设定匹配模式,正则表达式允许使用者在匹配模式中指定某一个范围而不局限于具体的字符。例如:
/[A-Z]/
上述正则表达式将会与从A到Z范围内任何一个大写字母相匹配。
/[a-z]/
上述正则表达式将会与从a到z范围内任何一个小写字母相匹配。
/[0-9]/
上述正则表达式将会与从0到9范围内任何一个数字相匹配。
/([a-z][A-Z][0-9])+/
上述正则表达式将会与任何由字母和数字组成的字符串,如“aB0”等相匹配。这里需要提醒用户注意的一点就是可以在正则表达式中使用“()”把字符串组合在一起。“()”符号包含的内容必须同时出现在目标对象中。因此,上述正则表达式将无法与诸如“abc”等的字符串匹配,因为“abc”中的最后一个字符为字母而非数字。
如果我们希望在正则表达式中实现类似编程逻辑中的“或”运算,在多个不同的模式中任选一个进行匹配的话,可以使用管道符“|”。例如:
/to|too|2/
上述正则表达式将会与目标对象中的“to”,“too”,或“2”相匹配。
正则表达式中还有一个较为常用的运算符,即否定符“[^]”。与我们前文所介绍的定位符“^”不同,否定符“[^]”规定目标对象中不能存在模式中所规定的字符串。例如:
/[^A-C]/
上述字符串将会与目标对象中除A,B,和C之外的任何字符相匹配。一般来说,当“^”出现在“[]”内时就被视做否定运算符;而当“^”位于“[]”之外,或没有“[]”时,则应当被视做定位符。
最后,当用户需要在正则表达式的模式中加入元字符,并查找其匹配对象时,可以使用转义符“/”。例如:
/Th/*/
上述正则表达式将会与目标对象中的“Th*”而非“The”等相匹配。
相关推荐
正则表达式基础学习笔记!!!从基础开始正则表达式基础学习笔记!!!
正则表达式基础正则表达式基础正则表达式基础正则表达式基础
vba正则表达式基础知识介绍,由浅入深,实例讲解
正则表达式基础语法及常用正则表达式及正则手册(HTML版)
Python正则表达式基础,译自官方文档Regular Expression HOWTO
该教程中所介绍的正则表达式应用仅仅是最为简单的(并没有完全地涉及到 Pattern 类支持的所有正则表达式语法,也没有涉及到高级的应用),适合于从未接触过或者是尚未完全明白正则表达式基础的学习者。在学习完该...
主要描述正则表达式的基础,包括正则表达式的格式,举例
javastript正则表达式基础 javastript正则表达式基础 javastript正则表达式基础
正则表达式基础入门教程 1. 本文目标 2. 如何使用本教程 3. 正则表达式到底是什么? 4. 入门 5. 测试正则表达式 6. 元字符 7. 字符转义 8. 重复 9. 字符类 10. 反义 11. 替换 12. 分组 13. 后向引用 14...
本文介绍了Python对于正则表达式的支持,包括正则表达式基础以及Python正则表达式标准库的完整介绍及使用示例。本文的内容不包括如何编写高效的正则表达式、如何优化正则表达式,这些主题请查看其他教程。 ...
正则表达式基础知识,对于初学者不错的指导。
正则表达式简介 为什么需要正则表达式? 文本的复杂处理。 正则表达式的优势和用途? 一种强大而灵活的文本处理工具; 提供了一种紧凑的、动态的方式,能够以一种完全通用的方式来解决各种字符串...
01C#正则表达式基础教程.doc
常用的正则表达式,包括正则表达式基础讲解,正则表达式格式、例子等
正则表达式基础知识正则表达式基础知识正则表达式基础知识
正则表达式基础知识!!! 我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配...
Groovy 正则表达式 Groovy正则表达式语法 背景项目使用Gradle作为自动化构建的工具, 闲暇之余对这个工具的使用方式以及其配置文件依赖的Groov
正则表达式 详解 基础 正则表达式之道(A Tao of Regular Expressions)
将正则表达式的基础知识浓缩到一张纸上,超实用~
本文介绍了深入学习正则表达式的基础知识和推荐内容。 本文主要面向对正则表达式知之甚少或没有使用经验,但却熟悉 ASP.NET、可借助 .NET 编程的初学者。此外,希望本文连同 regular expression cheat sheet 成为有...