
4.3 正则表达式
4.3.1 正则表达式简介

在编写处理字符串的程序或网页时,经常会查找符合某些复杂规则的字符串。正则表达式就是用于描述这些规则的工具。换言之,正则表达式就是记录文本规则的代码。对接触过DOS的用户来说,如果想匹配当前文件夹下的所有文本文件,则可以输入“dir *.txt”命令,按<Enter>键后所有“.txt”文件将会被列出来。这里的“*.txt”即可理解为一个简单的正则表达式。
4.3.2 行定位符

行定位符用来描述字符串的边界。“^”表示行的开始;“$”表示行的结尾。例如:

该表达式表示要匹配字符串tm的开始位置是行头,如tm equal Tomorrow Moon就可以匹配,而Tomorrow Moon equal tm则不匹配。如果使用:

则后者可以匹配而前者不能匹配。如果要匹配的字符串可以出现在字符串的任意部分,那么可以直接写成:

这样两个字符串就都可以匹配了。
4.3.3 元字符

现在你已经知道几个很有用的元字符了,如“^”“$”。正则表达式里还有很多元字符,下面来看看元字符的示例:

匹配以字母“mr”开头的单词,首先从某个单词开始处(\b)匹配字母“mr”,接着是任意数量的字母或数字(\w*),最后是单词结束处(\b)。该表达式可以匹配“mrsoft”“mrbook”“mr123456”等。常用的元字符如表4.2所示。
表4.2 常用的元字符

4.3.4 限定符

在前面章节的例子中,使用(\w*)匹配任意数量的字母或数字。如果想匹配特定数量的数字,那么该如何表示呢?正则表达式提供了限定符(指定数量的字符)来实现该功能。如匹配8位QQ号可用如下表示式:

常用的限定符如表4.3所示。
表4.3 常用的限定符

4.3.5 字符类

用正则表达式查找数字和字母是很简单的,因为已经有了对应这些字符集合的元字符(如\d,\w),如果要匹配没有预定义元字符的字符集合(比如元音字母a、e、i、o、u),应该怎么办?很简单,只需要在方括号里列出它们就可以了,比如[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(. 或 ? 或 !)。也可以轻松地指定一个字符范围,比如[0-9]的含意与\d就是完全一致的,即一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文)。
4.3.6 排除字符

前面的例子是匹配符合命名规则的变量。现在反过来,匹配不符合命名规则的变量,正则表达式提供了“^”元字符,这个元字符在4.3.1节中出现过,表示行的开始,而在这里将会把这个元字符放到方括号中,表示排除。例如:

该表达式匹配的就是不以字母开头的变量名。
4.3.7 选择字符

试想一下,如何匹配身份证号码?首先需要了解一下身份证号码的规则。身份证号码的长度为15位或18位。如果为15位时,则全为数字;如果为18位时,则前17位为数字,最后一位是校验位,可能为数字或字符X。
在前面的描述中,包含着条件选择的逻辑,这就需要使用选择字符(|)来实现。该字符可以理解为“或”,匹配身份证的表达式可以写成如下方式:

该表达式的意思是匹配15位数字或者18位数字,或者17位数字和最后一位。最后一位可以是数字或是X也或是x。
4.3.8 转义字符

正则表达式中的转义字符(\)和PHP中的大同小异,都是将特殊字符(如“.”“?”“\”等)变为普通字符。列举一个IP地址的实例,用正则表达式匹配诸如127.0.0.1这种格式的IP地址。如果直接使用点字符,则格式为:

这显然不对,因为“.”可以匹配一个任意字符。这时,不仅是127.0.0.1这种格式的IP,连127101011这样的字符串也会被匹配出来。所以在使用“.”时,需要使用转义字符(\)。修改后上面的正则表达式的格式为:

学习笔记
括号在正则表达式中也算是一个元字符。
4.3.9 分组

通过4.3.8节中的例子,相信读者已经对小括号的作用有了一定的了解。小括号的第一个作用就是可以改变限定符的作用范围,如“|”“*”“^”等。来看下面的一个表达式:

这个表达式的意思是匹配单词thirth或fourth,如果不使用小括号,那么就变成了匹配单词thir和fourth了。
小括号的第二个作用是分组,也就是子表达式,如(\.[0-9]{1,3}){3},就是对分组(\.[0-9]{1,3})进行重复操作。