Regular Expressions


来源:《学习正则表达式》(美) Michael Fitzgerald [著]、《Mastering Regular Expressions —— Third Edition》Jeffrey E. F. Friedl [著]。

“正则表达式是描述一组字符串特征的模式,用来匹配特定的字符串。”  ——  Ken Thompson

Regex Tester 是一个在线的用 JavaScript 实现的正则表达式处理器:http://www.regexpal.com/

界面更为美观的在线测试网站 RegExr 的 URL:http://regexr.com/

《学习正则表达式》书中的引例:采用各式各样的方法来匹配北美电话号码,其形式为 707-827-7019。

(1)用字符组来匹配数字:正则表达式 [0-9] 表示“匹配0到9范围内的任意数字”。方括号为元字符,不参与匹配。要匹配任意10位以连字符分隔的北美电话号码,可以使用正则表达式:[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9],这虽然可以,但是太长,更好的办法是采用简写模式。

(2)使用字符组简写式:\d 可以像 [0-9] 一样匹配任意阿拉伯数字,这种正则表达式称为字符组简写式,也称转义字符。因此可以采用正则表达式 \d\d\d-\d\d\d-\d\d\d\d 来匹配北美电话号码。点号 ‘.’ 是一个通配符,可以匹配任意字符,因此采用 \d\d\d.\d\d\d.\d\d\d\d 也可以进行匹配,但是它也可以匹配其他字符如 707%827%7019。

(3)捕获分组和后向引用:要创建捕获分组,先将一个 \d 放在一队圆括号中,这样就将它放在了一个分组中,后面可以用 \1 来对捕获的内容进行后向引用:(\d)\d\1,\1 对括号内分组捕获的内容进行了后向引用。现在可以用一个捕获分组和几个后向引用对整个电话号码进行匹配:(\d)0\1-\d\d\1-\1\d\d\d

(4)使用量词:现在采用另一种语法来匹配电话号码:\d{3}-?\d{3}-?\d{4},花括号中的数字表示待匹配的数字出现的次数,包含数字的花括号是一种量词,花括号本身是元字符。问号是另一种量词,表示以上表达式中的连字符可以出现零次或一次,也就是可选的,其他量词如加号 ‘+’ 表示 “一个或多个”、星号 ‘*’ 表示 “零个或多个”。使用量词能使得正则表达式更为简洁:(\d{3,4}[.-]?)+,最后的加号表示括号里的模式出现一次或多次,括号里的模式匹配三位或四位数字,后跟一个连字符或一个点号。该表达式能用但不完全对,因为形式 7078-277-019 也能匹配,因此需要改进一下:(\d{3}[.-]?){2}\d{4}

(5)括选文字符:最后这个正则表达式表示第一个 3 位数字可以带或不带括号,即区号是可选的:^(\(\d{3}\)|^\d{3}[.-]?)?\d{3}[.-]?\d{4}$,为便于理解,依次看一下表达式中的各项:

  • 出现在正则表达式起始位置或者竖线 ‘|’ 之后的脱字符 ^ 表示电话号码会出现在一行的起始位置;
  • 左括号 ( 为捕获分组的起始符;
  • \( 表示左括号本身;
  • \d{3} 表示匹配三位数字;
  • \) 匹配右括号本身;
  • 竖线符 | 表示选择,也就是从多个可选项中选择一个,此处表示 “匹配一个带括号的区号或者不带括号的区号”;
  • 脱字符 ^ 匹配行起始位置;
  • \d{3} 表示匹配三位数字;
  • [.-]? 匹配一个可选的点号或连字符;
  • 右括号 ) 为捕获分组的结束符;
  • 问号 ? 表示分组可选,即分组中的前缀可有可无;
  • \d{3} 表示匹配三位数字;
  • [.-]? 匹配另一个可选的点号或连字符;
  • \d{4} 表示匹配四位数字;
  • 美元符 $ 匹配行结束位置。

该表达式最终匹配十位的北美电话号码,而且括号、连字符或者点号都是可选的。

在 Goyvaerts 和 Levithan 合著的 《Regular Expressions Cookbook》 一书中有一个更为可靠的匹配电话号码的正则表达式:^\(?(?:\d{3})\)?[.-]?(?:\d{3})[.-]?(?:\d{4})$

  • ^ 是判定一行或者主题词开头的零宽度断言;
  • \(? 是一个可选的字面左括号;
  • (?:\d{3}) 是一个匹配连续三位数字的非捕获分组;
  • \)? 是一个可选的字面右括号;
  • [.-]? 匹配一个可选的点号或连字符;
  • (?:\d{4}) 是一个匹配连续四位数字的非捕获分组;
  • $ 用以匹配一行或主题词的结尾。

 

最后,由 Grant Skinner 用 RegExr 提供的表达式改编出来了一个用以匹配电子邮件地址的正则表达式:^([\w-.!#$%&’*+-/=?^_`{|}~]+)@((?:\w+\.)+)(?:[a-zA-Z]{2,4})$

未完待续…

Leave a comment

邮箱地址不会被公开。 必填项已用*标注