4.2 正则表达式入门
正则表达式是基于样式匹配的文本处理技术的关键所在。想要在编写文本处理工具方面驾轻就熟,你就必须对正则表达式有一个基本的理解。正则表达式是一种用于文本匹配的形式小巧、具有高度针对性的编程语言。只依靠通配符技术,能够匹配的文本范围相当有限。这则攻略将对基础的正则表达式进行讲解。
4.2.1 预备知识
正则表达式是用于绝大多数文本处理工具的一种语言。因此你完全可以把在这里学习到的技术应用到其他攻略中。[a-z0-9_]+@[a-z0-9]+.[a-z]+
就是一个能够匹配电子邮件地址的正则表达式。
它看起来是不是很古怪?别担心,一旦你理解了相关的概念,它其实相当简单。
4.2.2 实战演练
本节将会让你简单了解一下正则表达式、POSIX字符类(POSIX character class)以及元字符(meta character)。
先来看一看正则表达式的基本组成部分,如表4-1所示。
表 4-1
正则表达式 | 描 述 | 示 例 |
---|---|---|
^ | 行起始标记 | ^tux 匹配以tux起始的行 |
$ | 行尾标记 | tux$ 匹配以tux结尾的行 |
. | 匹配任意一个字符 | Hack. 匹配Hackl和Hacki,但是不能匹配Hackl2和Hackil,它只能匹配单个字符 |
[] | 匹配包含在 [字符] 之中的任意一个字符 | coo[kl] 匹配cook或cool |
[^] | 匹配除 [^字符] 之外的任意一个字符 | 9[^01] 匹配92、93,但是不匹配91或90 |
[-] | 匹配 [] 中指定范围内的任意一个字符 | [1-5] 匹配从1~5的任意一个数字 |
? | 匹配之前的项1次或0次 | colou?r 匹配color或colour,但是不能匹配colouur |
+ | 匹配之前的项1次或多次 | Rollno-9+ 匹配Rollno-99、Rollno-9,但是不能匹配Rollno- |
* | 匹配之前的项0次或多次 | co*l 匹配cl、col、coool等 |
() | 创建一个用于匹配的子串 | ma(tri)?x 匹配max或maxtrix |
{n} | 匹配之前的项n次 | [0-9]{3} 匹配任意一个三位数,[0-9]{3} 可以扩展为[0-9][0-9][0-9] |
{n,} | 之前的项至少需要匹配n次 | [0-9]{2,} 匹配任意一个两位或更多位的数字 |
{n,m} | 指定之前的项所必需匹配的最小次数和最大次数 | [0-9]{2,5} 匹配从两位数到五位数之间的任意一个数字 |
| | 交替——匹配 | 两边的任意一项 | Oct (1st | 2nd) 匹配Oct 1st 或Oct 2nd |
\ | 转义符可以将上面介绍的特殊字符进行转义 | a.b 匹配a.b,但不能匹配ajb。通过在 . 之间加上前缀 \ ,从而忽略了 . 的特殊意义 |
POSIX字符类是一个形如 [:…:]
的特殊元序列(meta sequence),它可以用于匹配特定的字符范围。POSIX字符类如表4-2所示。
表 4-2
正则表达式 | 描 述 | 示 例 |
---|---|---|
[:alnum:] | 字母与数字字符 | [[:alnum:]]+ |
[:alpha:] | 字母字符(包括大写字母与小写字母) | [[:alpha:]]{4} |
[:blank:] | 空格与制表符 | [[:blank:]]* |
[:digit:] | 数字字符 | [[:digit:]]? |
[:lower:] | 小写字母 | [[:lower:]]{5,} |
[:upper:] | 大写字母 | ([[:upper:]]+)? |
[:punct:] | 标点符号 | [[:punct:]] |
[:space:] | 包括换行符、回车等在内的所有空白字符 | [[:space:]]+ |
元字符是一种Perl风格的正则表达式,只有一部分文本处理工具支持它,并不是所有的工具都支持表4-3中所列的字符,但是之前介绍的正则表达式和字符类都是被广泛支持的。
表 4-3
正则表达式 | 描 述 | 示 例 |
---|---|---|
\b | 单词边界 | \bcool\b 匹配cool,但不匹配coolant |
\B | 非单词边界 | cool\B 匹配coolant,但不匹配cool |
\d | 单个数字字符 | b\db 匹配b2b,但不匹配bcb |
\D | 单个非数字字符 | b\Db 匹配bcb,但不匹配b2b |
\w | 单个单词字符(字母、数字与 _ ) | \w 匹配1或a,但不匹配 & |
\W | 单个非单词字符 | \W 匹配&,但不匹配1或a |
\n | 换行符 | \n 匹配一个新行 |
\s | 单个空白字符 | x\sx 匹配x x,但不匹配xx |
\S | 单个非空白字符 | \x\S\x 匹配xkx,但不匹配xx |
\r | 回车 | \r 匹配回车 |
4.2.3 工作原理
在4.2.2节中看到的表格是正则表达式的关键元素表。在表中挑选恰当的正则表达式,我们就能够根据需要构建出适合的正则表达式来匹配文本。正则表达式是一种用于文本匹配的通用语言。因此我们在这则攻略中不会介绍任何工具,而是把这个任务放到本章的其他攻略中。
来看几个文本匹配的例子。
- 为了匹配给定文本中的所有单词,可以使用下面的正则表达式:
( ?[a-zA-Z]+ ?)
“?
”用于匹配单词前后可能出现的空格。[a-zA-Z]+
代表一个或多个字母(a~z和A~Z)。
- 为了匹配一个IP地址,可以使用下面的正则表达式:
- [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
或者
- [[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}
我们知道IP地址通常的书写形式是192.168.0.2,它是由点号分割的4个整数(每一个整数的取值范围从0到255)。
[0-9]
或[:digit:]
匹配数字0~9。{1,3}
匹配1到3个数字,.
匹配"."
。
4.2.4 补充内容
下面就看一看如何在正则表达式中指定某些字符的特殊含义。
处理特殊字符
正则表达式用$
、^
、.
、*
、+
、{
以及}
等作为特殊字符。但是如果我们希望将这些字符作为非特殊字符(表示普通字面含义的字符)来使用的话,应该怎么做呢?来看一个例子。
正则表达式:[a-z]*.[0-9]
那么,它是什么意思?
它可以匹配0个或多个a-z
,接任意单个字符(.
),再接[0-9]
中的任意一个字符,所以它能够匹配 abcdeO9
。
它也可以理解成:匹配[a-z]
中任意一个字符,接单个字符*
,再接单个字符.
(点号),最后接一个数字,所以它能够匹配x*.8
。
为了避免这种理解上的混乱,我们可以在字符前面放上一个“\
”(这种做法称为“对字符进行转义”)。对于像 *
这种具有多种含义的字符,可以在前面加上“\
”,使其具备或丧失某些特殊的含义。至于转义后字符的意义是否具备特殊的含义,则取决于你所使用的工具。