21.2 正则表达式的语法
仅从概念上了解正则表达式是没有实际作用的,要理解、掌握直至熟练应用正则表达式,还是需要从正则表达式的构成等方面深入了解正则表达式。本节将介绍正则表达式的基本语法,简述如何通过这些语法构建一个正则表达式。本节涉及很多符号以及这些符号的使用规则,有的符号在正则表达式不同的位置所表示的含义完全不同,所以读者需要仔细阅读,用心揣摩。对一些需要重点理解的地方,笔者使用了粗体字加以强调,读者需对这些讲述认真理解。
21.2.1 模式
模式是正则表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂。模式往往用一些特殊的字符表示某个范围内的字符、字符重复出现次数、字符是否应该出现等。
示例如下。
^once
^once就是一个模式。这个模式包含一个特殊的字符^,该符号表示该模式只匹配那些以once开头的字符串。例如该模式与字符串“once you begin,you must continue”匹配,与“all at once she lost her temper”不匹配。正如“^”符号表示开头一样,“$”符号用来匹配那些以给定模式结尾的字符串。
例如如下示例。
PHP$
这个模式与I'm learning PHP匹配,与I'm learning Perl不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。
例如如下示例。
^Python$
这个模式只匹配Python本身。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。
例如下面的示例。
once
这个模式可以匹配“once is enough,never again”、“He stopped playing the piano at once”、“Harry is home from school once again”等字符串,甚至可以匹配“Who kept all of his cash in a bucket。”因为o-n-c-e每个字母本身都出现在了这个字符串当中,它们都是字面字符,并不一定要组合在一起出现在字符串中。
从上述模式的例子中可以看到,符号^、$在正则表达式中有特殊的含义,类似的符号还有很多,在下面的内容中将有更详细的介绍。
21.2.2 元字符
正则表达式是定义了字符串匹配规则的字符串。该字符串是由普通字符(例如字符a到z)以及特殊字符组成的文字模式。普通字符通常包括所有大写和小写字母字符、所有数字、所有标点符号以及一些特殊符号。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。例如,正则表达式Mac*所表达的含义是所有包含Mac并且Mac后跟零个或多个字符的字符串,如Mack、Macintosh以及Mac本身都符合这个正则表达式所定的规则。Mac*中的星号*有其特殊含义,它表示一个或多个字符。
类似星号*这种有特殊含义的字符在正则表达式中还有很多,这样的字符叫做元字符。正则表达式中的元字符有^、$、[]、\、.、|、?、*、+、()。这些字符被保留下来,有其特殊用途。下面就分别介绍这些元字符的用途。
1.位置匹配元字符
·元字符^:用来匹配以指定字符(或字符串)开头的字符串。例如,模式^hell可以匹配hello,hell等,但其不匹配holla。
·美元符号$:用来匹配以指定字符(或字符串)结尾的字符串。例如,ow$可以匹配low、fellow等,这些字符串均以ow结尾。
·英文句点.:用来匹配除\n之外的任何单个字符。例如,要找出3个字母的单词,而且这些单词必须以字母“b”开头,以“s”字母结束。通常可以使用这个通配符——英文句点符号“.”。这样,完整的模式就是“b.s”,这就是一个正则表达式,它可以匹配的3个字母的单词,这些单词可以是“bes”、“bis”、“bos”和“bus”。事实上,这个正则表达式还可以匹配“b3s”、“b#s”甚至“b s”,还有其他许多无实际意义的组合。又如,模式“^.5$”匹配以数字5结尾和以其他非换行字符开头的字符串。模式.可以匹配任何字符串,除了空串和只包含一个换行字符的字符串。
·方括号[]:为了解决句点符号匹配范围过于宽泛的问题,可以方括号“[]”来指定匹配范围,可以在方括号内指定有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“b[eiou]s”只匹配“bes”、“bis”、“bos”和“bus”。但“bees”不匹配,因为在方括号之内只能匹配单个字符。例如,[a-z]用来匹配所有小写字母,但只能匹配一个字母。注意,通常用符号-连接匹配范围的首尾。
·或操作符号|:可以完成在两项或多项之间选择一个进行匹配。对于上述的例子,如果还想匹配“boos”,那么以使用操作符“|”。操作符“|”的基本意义就是“或”运算,所以,正则表达式“b(a|e|i|o|oo)s”可以匹配“boos”。特别注意,这里不能使用方括号,必须使用圆括号“()”,因为方括号只允许匹配单个字符。圆括号还可以用来分组,后面的小节会有介绍。如果希望在正则表达式中实现类似编程逻辑中的“或”运算,在多个不同的模式中任选一个进行匹配,就可以使用元字符|。
·\:用来转义一个字符。对于一些特殊的符号的匹配,如元字符本身和空格、制表符等,需要用到转义,所有的转义序列都用以\(反斜杠)为前缀。例如,要在正则表达式中匹配元字符$,就需要使用\$,匹配元字符\就要使用\\。关于转义字符更多的内容,将在21.2.3小节介绍。
·():标记一个子表达式的开始和结束位置,即括住一个表达式。
2.次数匹配元字符
以上介绍的元字符基本可以看作是对字符(或字符串)位置的匹配,下面介绍和匹配次数有关的一些元字符。这些元字符用来确定紧靠该符号左边的符号出现的次数。注意,这里强调了“紧靠左边”这一原则。
·*:匹配其左边(即前面)的子表达式0次或多次。例如,pe*匹配perl、peel、pet、port等,因为这些字符串都符合(即匹配)在字母p后连续出现0个或多个字母e。
·+:匹配其左边(即前面)的子表达式1次或多次,注意,与*不同,+前的字符至少要出现1次,例如,co+匹配come、code、cool、co等,这些字符串都匹配在字母c后至少出现1个或多个字母o。
·?:匹配其左边(即前面)的子表达式0次或1次。
注意 *、+和?只对紧挨它的前面那个字符起作用。还有其他几种表示法可以限定匹配次数,这些内容将在21.2.5小节介绍。
21.2.3 转义字符
正则表达式中的转义,除了需要对元字符转义之外,还有一些非打印字符在匹配时需要转义。这些字符及其含义见表21-1。
表21-1 非打印字符的转义含义
21.2.4 字符类
PHP的正则表达式有一些内置的通用字符类,可以在正则表达式中直接使用这些字符类,完成对各种字符的匹配,这种字符类的用法相对简单一些。PHP正则表达式通用的字符类包括以下内容。
·[[:alpha:]]:表示匹配任何字母。
·[[:digit:]]:表示匹配任何数字。
·[[:alnum:]]:表示匹配任何字母和数字。
·[[:space:]]:表示匹配任何白字符。
·[[:upper:]]:表示匹配任何大写字母。
·[[:lower:]]:表示匹配任何小写字母。
·[[:punct:]]:表示匹配任何标点符号。
·[[:xdigit:]]:表示匹配任何十六进制的数字,相当于[0-9a-fA-F]。
·[[:blank:]]:表示空格和TAB,等价于[\t]。
·[[:cntrl:]]:表示匹配所有ASCII码值在0~31之间的控制符。
·[[:graph:]]:表示匹配所有的可打印字符,等价于[^\t\n\r\f\v]。
·[[:print:]]:表示匹配所有的可打印字符和空格,等价于[^\t\n\r\f\v]。
例如,^[[:alpha:]]{3}$匹配所有的3个字母的单词。
21.2.5 反义
PHP正则表达式反义匹配主要有以下几种。
·\W:匹配任意不是子母、数字、下划线或汉字的字符。
·\S:匹配任意不是空白符的字符。
·\D:匹配任意非数字的字符。
·\B:匹配不是单词开头或结束的位置,即一个词语的边界,位于\w和\W之间的位置。
例如,\S+匹配不包含空白符的字符串,<a[^>]+>匹配用尖括号括起来的以a开头的字符串。
21.2.6 数量匹配限定符
数量限定符用来指定正则表达式中,一个给定组合必须出现多少次才能满足匹配。在21.2.2小节中介绍元字符时,对一部分匹配限定符有所介绍,它们是*、+、?。本小节将要介绍另外一种匹配限定符,使用这一类限定符也可以完成对字符出现次数的匹配。
使用符号“{}”可以确定其左边(即前面)的内容重复出现的次数。在{}内指定字符出现的次数,通常有3种表示法,如下所述。
·{n}:表示匹配该限定符左边字符n次。例如a{3},该模式表示匹配连续出现3个a的字符串,它可以匹配aaa、cacaaad、aacoaaao等。
·{n,}:表示匹配该限定符左边字符n次或多次,即至少匹配n次。例如a{3,},匹配aaa、aaab、caaaaa等,但不匹配aa等。
·{n,m}:表示匹配该限定符左边字符至少n次,但最多不超过m次。例如a{1,3}b,匹配ab、aab、aaab,但不匹配aaaab。
下面把用来匹配字符出现次数的限定符加以总结,使读者对匹配限定符有整体上的认识和把握。这些数量匹配限定符及其含义如表21-2所示。
表21-2 数量匹配限定符及其含义
提示 限定符*、+和?会尽可能多地匹配字符,因此被称作“贪婪”匹配,只要在它们的后面加上一个?,就可以实现所谓的非贪婪或最小匹配。
21.2.7 正则表达式构建实例
本节将综合以上几小节知识,通过对一些正则表达式的构成分析,来进一步理解前文学习到的知识。另外举一些实例,来学习如何创建一个正则表达式。下面先分析几个比较简单的正则表达式。
·ab*:和ab{0,}同义,匹配以a开头,后面可以接0个或者n个b组成的字符串,如a、ab、abbb等。
·ab+:和ab{1,}同义,但最少要有1个b存在,如ab、abbb等。
·ab?:和ab{0,1}同义,可以没有或者只有1个b,如a、ab。
·a?b+$,匹配以1个或者0个a再加上1个以上的b为结尾的字符串,如ab、abb等。
以上几个正则表达式示例只是匹配单一字符,如果想匹配多个字符,可以使用()将需要匹配的字符括住。下面是几个示例正则表达式。
·a(bc)*:匹配a后面跟0个或者1个bc的字符串。如该模式可以匹配a、abc、abcbc等。
而使用中括号括住的内容只能匹配一个字符。例如如下正则表达式。
·[ab]:匹配单个的a或者b,该模式和a│b同义。如匹配a、b。
·[a-d]:匹配a到d的单个字符,该模式和a│b│c│d及[abcd]同义。
下面看几个稍微复杂的正则表达式。
·^[a-zA-Z_]$:匹配所有的只有字母和下划线的字符串。这里之所以在模式开头加上^在模式结尾加上$,是为了匹配只含有字母和下划线的字符串,是因为,如果不加^和$,那么凡是含有字母和下划线的字符串均会被匹配。
·^[a-zA-Z0-9_]{1,}$:匹配所有包含一个以上的字母、数字或下划线的字符串。
·^[0-9]{1,}$:匹配所有正数。
·^\-{0,1}[0-9]{1,}$:匹配所有的整数,含负数,在负号前加转义符号\。
·^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$:匹配所有小数。
共有条评论 网友评论