14.4.4 有用的正则表达式

创建正则表达式也有其自身的挑战。不仅需要理解不同的正则表达式字符是如何工作的,还必须搞清楚针对不同可能的搜索的合适的模式。例如,如果你想要找到邮政编码的一个匹配,你需要考虑到邮政编码可能只有5个数字(97213)或者5+4个数字(97213-3333)的事实。为了帮助你开始使用正则表达式,这里介绍一些常用的正则表达式。

提示:如果你不喜欢输入这些正则表达式(谁也不能怪你),可以在本书教程chapter14文件夹下名为example_regex.txt的文件中找到已经设置好的正则表达式。

美国邮政编码

邮政编码在各个国家都不同,但是,在美国,它们要么是5个数字,要么是5个数字后面跟着一个连字符和4个数字。如下是匹配这两种选项的正则表达式:


\d{5}(-\d{4})?


注意:要了解与其他国家的邮政编码匹配的正则表达式,请访问http://regexlib.com/Search.aspx?k=postal+code。

该正则表达式可以划分为如下几个较小的部分:

·\d{5}匹配5个数字,例如97213。

·()创建一个子模式。圆括号之间的任何内容都看做需要匹配的一个单个模式。稍后,我们将看到为什么这很重要。

·-\d{4}匹配一个连字符后面跟着4个数字,例如-1234。

·匹配之前的模式的0次或1次实例。在这里是圆括号出现的部分,(-\d{4})当做一个单个的部分对单,因此,?意味着匹配一个连字号后面跟着4个数字的0次或一次实例。由于你不一定必须包含连字符+4个数字,这个模式可能出现0次。换句话说,如果测试97213这样的一个值,将会得到一个匹配,因为连字号后面跟着4个数字这是可选的。

注意:要确保整个字符串匹配一个正则表达式,以^开始一个正则表达式,并且以一个$结束它。例如,如果想要确保某人只能在邮政编码表格字段输入一个格式有效的邮政编码,使用正则表达式^\d{5}(-\d{4})?$来防止“blah 97213 blah blah”之类的一条回应。

美国电话号码

美国电话号码由一个3位的区号以及后面跟着7位数字组成。然而,人们也有很多种不同的方式来写电话号码,例如,503-555-1212、(503)555-1212、503.555.1212或者只是503 555 1212。用于这一模式的一个正则表达式是:


\(?(\d{3})\)?[-.](\d{3})[-.](\d{4})


注意:对于匹配其他国家的电话号码的正则表达式,请访问http://regex-lib.com/Search.aspx?k=phone+number。

这个正则表达式看上去有些复杂,但是,如果将其细分(下面进行了很好地解释),其含义就清楚了:

·\(匹配一个字面的开始圆括号字符。因为圆括号用来分组模式(参见前面的邮政编码示例),开始圆括号在正则表达式中具有特殊的含义。要告诉JavaScript解释器匹配一个实际的开始圆括号,我们需要使用反斜杠字符将字符转义(就像2.3.3节介绍的转义引号)。

·?表示(符号是可选的,因此,像503-555-1212这样不带圆括号的电话号码仍然匹配。

·(\d{3})是一个子模式,匹配任意3个数字。

·\)?匹配一个可选的结束圆括号。

·[-.]匹配一个空格、连字符或句点(注意,通常你必须像.这样转义一个句点,以告诉JavaScript解释器,我们想要匹配一个句点字符,而不是将其当做一个特殊的正则表达式符号来匹配任何字符;然而,当在一个方括号之内的时候,一个句点总是当做字面值对待)。

·(\d{3})是匹配任意3个数字的另一个子模式。

·[-.]匹配一个空格、连字符或句点

·(\d{4})是最后的一个子模式,它匹配任意4个数字。

注意:子模式是出现在圆括号中的模式,例如,上面的电话号码正则表达式中的(\d{3})。正如本书14.2.7节所述,当使用replace()方法的时候,它们用起来很方便。

E-mail地址

在接受来自表单的用户输入的时候,检查一个有效的E-mail地址也是一种常见的任务。很多人试图使用类似“none of your business”的一条回应来避免提供有效的E-mail地址,或者人们只是输错了自己的E-mail地址(例如,missing@sawmac.commm)。如下的正则表达式可以检查一个字符串是否包含了格式正确的E-mail地址:


[-\w.]+@([A-z0-9][-A-z0-9]+.)+[A-z]{2,4}


注意:这个正则表达式并不检查一个地址是否是某个人的真实有效的E-mail地址,它只是检查其格式是否像是一个真正的E-mail地址。

这个正则表达式可以分解如下:

·[-\w.]+匹配一个连字符、任意个单词字符或者一个句点一次或多次。因此,它将匹配“bob”、“bob.smith”或“bob-smith”。

·@是E-mail地址中的@符号,例如,missing@sawmac.com。

·[A-z0-9]匹配一个字母或数字。

·[-A-z0-9]+匹配一个字母、数字或连字符的一个或多个实例。

·.是一个句点字符,因此,它将匹配sawmac.com(http://www.sawmac.com)中的句点。

·+匹配包含了上面提到的3个匹配的模式的一个或多个实例。这个字符考虑到类似bob@mail.sawmac.com中的子域名。

·[A-z]{2,4}是任意字母的2次3次或4次匹配。这会匹配.com中的com或.uk中的uk。

注意:上面列出的E-mail正则表达式并不会匹配所有技术上有效的E-mail地址。例如,!#$%&’*+-/=?^_.{|}~@example.com从技术上讲是一个有效的E-mail地址,但是,这里描述的正则表达式无法匹配它。它涉及找到人们实际可能使用的E-mail地址。如果你想要更加精确,可以使用如下的正则表达式。注意,将其作为单独一行输入:


/^[\w!#$%&\’+\/=?^{|}~.-]+@(?:[a-z\d][a-z\d-](?:.[a-z\d][a-z\d-]*)?)+.(?:[a-z][a-z\d-]+)$/i


日期

日期也可以以很多不同的方式书写,例如,09/28/2007、9-28-2007、09 28 2007或者甚至是09.28.2007(这些只是美国常用的格式。在世界上其他的地方,日期出现在月份之前,如28.09.2007)。由于访问者可能以这些格式的任意一种输入一个日期,因此,我们需要一种方式来检查他们是否提供了一个格式有效的日期。(在14.4.3节)你将了解到如何将这些格式的任意一种转换为一个单个的、标准的格式,以便确保你从一个表单上接收的所有日期都是格式正确的。)

下面是检查一个正确输入的日期的正则表达式:


([01]?d)[-\/.]([0123]?\d)[-\/.](\d{4})


·()将接下来的两个正则表达式模式括起来,以将它们分组。它们一起组成了表示月份的数字。

·[01]?匹配0或者1,?使其成为可选的。这用于月份的第一个数字。显然,它不能比1大,因为没有22月。此外,如果月份是从1~9月,你可能只会得到5而不是05。这就是为什么它是可选的。

·\d匹配任意的数字。

·[-\/.]将匹配一个连字符、反斜杠、句点或空格字符。这是月份和日期直接可接收的分隔符,例如,10/21、1021、10.21或10-21。

·()是下一个子模式,它用来捕获日期。

·[0123]?匹配0、1、2或3 0次或一次。由于一月中没有第40天,我们将日期的第一个数字限制在这4个数字之一。这个模式是可选的(由?所确定的),因为一些人可能输入9而不是09来表示日期。

·\d匹配任何数字。

·[-\/.]和上面所述的一样。

·()捕获年份。

·\d{4}匹配4个数字,例如1908或2880。

Web地址

如果你要求访问者输入其Web地址,并且你想要确认他提供了一个Web地址,或者如果你想要扫描某些文本并识别出列出的每个URL,那么,匹配一个Web地址是很有用的。用于URL的一个基本的正则表达式如下:


((\bhttps?:\/\/)|(\bwww.))\S*


这个表达式有点复杂,因为,它使用了很多圆括号来分组表达式的不同部分。图14-4可以帮助你理解这一正则表达式。一对圆括号(#1)将两个其他的圆括号(#2和#3)包括起来。两个组之间的|符号表示“或”的意思。换句话说,正则表达式需要匹配#2或者#3。

14.4.4 有用的正则表达式 - 图1

图 14-4 你可以使用圆括号分组表达式,并且使用|(管道)符号来查找两个表达式之一。例如,外围的表达式(#1)将匹配与#2或#3匹配的任何文本

·(是外围组的开始(图14-4中的#1)。

·(是内层组的开始(图14-4中的#2)。

·\b匹配一个单词的开始。

·http匹配以http开始的完整的Web地址的开始。

·s?是可选的。因为Web页面可能通过一个安全连接发送,一个有效的Web地址也可能是以https开头的。

·:\/\/匹配://。因为反斜杠在正则表达式中有特殊的含义,因此,需要在其前面放置一个斜杠,以使其匹配反斜杠字符。

·)是内层组的结束(图14-4中的#2)。综合起来,这个组将匹配http://或https://。

·|匹配一个组或另一个组(图14-4中的#2或#3)。

·(是第二个内层组的开始(图14-4中的#3)。

·\b匹配一个单词的开始。

·www.匹配www.。

·)是第二个内层组的结束(图14-4中的#3)。这个组将捕获没有http://但以www开始的一个URL。

·)是外层组的结束(图14-4中的#1)。此时,正则表达式将匹配以http://、https://或www开始的文本。

·\S*匹配一个或多个非空格字符。

这个表达式并不是非常安全的(例如,它无法匹配一个类似http://#$%&@*的无意义的URL),但是,它相对比较简单,并且可以成功地匹配类似http://www.sawmac.com/missing/js/index.html的一个真正的URL。

提示:要查看一个字符串是否包含一个URL(在URL之前或之后没有其他内容),在正则表达式的开始使用^符号,在其末尾使用$字符,并且删除掉\b字符:^((https?:\/\/)|(www.))\S*$