有些人在碰到问题时,就想:“我知道,我可以使用正则表达式。”现在,他们就有了两个问题。
—Jamie“jwz” Zawinski, 1997 年 8 月
正则表达式为高级的文本模式匹配、抽取、与/或文本形式的搜索和替换功能提供了基础。简单地说,正则表达式(简称为 regex)是一些由字符和特殊符号组成的字符串,它们描述了模式的重复或者表述多个字符,于是正则表达式能按照某种模式匹配一系列有相似特征的字符串。
“搜索”(searching),即在字符串任意部分中搜索匹配的模式,通过 search()函数或方法来实现。
“匹配”(matching)是指判断一个字符串能否从起始处全部或者部分地匹配某个模式,调用 match()函数或方法实现。
常见正则表达式符号和特殊字符
表示法 | 描述 | 正则表达式示例 |
符号 | ||
literal(普通字母) | 匹配文本字符串的字面值literal | foo |
re1 | re2 | 匹配正则表达式re1 或者 re2 | foo | bar |
. | 匹配任何字符(除了\n之外) | b.b |
^ | 匹配字符串起始部分 | ^Dear |
$ | 匹配字符串终止部分 | /bin/*sh$ |
* | 匹配0次或者多次前面出现的正则表达式 | [A-Za-z0-9]* |
+ | 匹配1次或者多次前面出现的正则表达式 | [a-z]+\.com |
? | 匹配0次或者1次前面出现的正则表达式 | goo? |
{N} | 匹配N次前面出现的正则表达式 | [0-9]{3} |
{M,N} | 匹配M~N次前面出现的正则表达式 | [0-9]{5,9} |
[…] | 匹配来自字符集的任意单一字符 | [aeiou] |
[..x-y..] | 匹配x~y范围中任意单一字符 | [0-9], [A-Za-z] |
[^…] | 不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在此字符集中出现) | [^aeiou], [^A-Za-z0-9] |
(*|+|?|{})? | 用于匹配上面频繁出现/重复出现符号的非贪婪版本(*、+、?、{}) | .*?[a-z] |
(…) | 匹配封闭的正则表达式,然后另存为子组 | ([0-9]{3})?,f(oo|u)bar |
特殊字符 | ||
\d | 匹配任何十进制数字,与[0-9]一致(\D 与\d 相反,不匹配任何非数值型的数字) | data\d+.txt |
\w | 匹配任何字母数字字符,与[A-Za-z0-9_]相同(\W 与之相反) | [A-Za-z_]\w+ |
\s | 匹配任何空格字符,与[\n\t\r\v\f]相同(\S 与之相反) | of\sthe |
\b | 匹配任何单词边界(\B 与之相反) | \bThe\b |
\N | 匹配已保存的子组 N(参见上面的(…)) | price: \16 |
\c | 逐字匹配任何特殊字符 c(即,仅按照字面意义匹配,不匹配特殊含义) | \., \\, \* |
\A(\Z) | 匹配字符串的起始(结束)(另见上面介绍的^和$) | \ADear |
扩展表示法 | ||
(?iLmsux) | 在正则表达式中嵌入一个或者多个特殊“标记” 参数(或者通过函数/方法) | (?x),(? im) |
(?:…) | 表示一个匹配不用保存的分组 | (?:\w+\.)* |
(?P<name>) | 像一个仅由 name 标识而不是数字 ID 标识的正则分组匹配 | (?P<data>) |
(?P=name) | 在同一字符串中匹配由(?P<name)分组的之前文本 | (?P=data) |
(?#...) | 表示注释,所有内容都被忽略 | (?#comment) |
(?=…) | 匹配条件是如果…出现在之后的位置,而不使用输入字符串;称作正向前视断言 | (?=.com) |
(?!...) | 匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言 | (?!.net) |
(?<=…) | 匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言 | (?<=800-) |
(?<!...) | 匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言 | (?<!192\.168\.) |
(?(id/name)Y|N) | 如果分组所提供的 id 或者 name(名称)存在,就返回正则表达式的条件匹配 Y,如 果不存在,就返回 N; |N 是可选项 | (?(1)y|x) |
- 使用择一匹配符号匹配多个正则表达式模式表示择一匹配的管道符号( | ),就是键盘上的竖线,表示一个“从多个模式中选择其一”的操作,用于分割不同的正则表达式。
- 匹配任意单个字节点号或者句点(.)符号匹配除了换行符\n以外的任何字符。注意:若要匹配句点(dot)或者句号(period)字符,则必须使用反斜线转义句点符号的功能,例如“\.”。
- 从字符串起始或者结尾或者单词边界匹配
正则表达式模式 | 匹配的字符串 |
^From | 任何以From作为起始的字符串 |
/bin/tcsh$ | 任何以/bin/tcsh作为结尾的字符串 |
^Subject:hi$ | 任何由单独的字符串Subject:hi构成的字符串 |
4. 创建字符集尽管句点可以用于匹配任意符号,但某些时候,可能想要匹配某些特定字符。正因如此,发明了方括号。该正则表达式能够匹配一对方括号中包含的任何字符。
正则表达式模式 | 匹配的字符串 |
b[aeiu]t | bat、bet、bit、but |
5.限定范围和否定除了单字符以外,字符集还支持匹配指定的字符范围。方括号中两个符号中间用连字符(-)连接,用于指定一个字符的范围;例如, A-Z、 a-z 或者 0-9 分别用于表示大写字母、 小写字母和数值数字。这是一个按照字母顺序的范围,所以不能将它们仅仅限定用于字母和十进制数字上。另外,如果脱字符(^)紧跟在左方括号后面,这个符号就表示不匹配给定字符集中的任何一个字符。
正则表达式模式 | 匹配的字符串 |
z[0-3] | z0、z1、z2、z3 |
[r-t][x-z] | rx、ry、rz、sx、sy、sz、tx、ty、tz |
[^aeiou] | 非a、e、i、o、u的单个字符 |
6.使用闭包操作符实现存在性和频数匹配特殊符号*、 +和?,所有这些都可以用于匹配一个、 多个或者没有出现的字符串模式。大括号操作符({}),里面或者是单个值或者是一对由逗号分隔的值。这将最终精确地匹配前面的正则表达式 N 次(如果是{N})或者一定范围的次数;例如, {M, N}将匹配 M~N 次出现。
正则表达式模式 | 匹配的字符串 |
[dn]ot? | do、dot、no、not |
[0-9]{15,16} | 匹配15或者16个数字 |
7. 表示字符集的特殊字符与使用“0-9”这个范围表示十进制数相比,可以简单地使用 d 表示匹配任何十进制数字。另一个特殊字符(\w) 能够用于表示全部字母数字的字符集,相当于[A-Za-z0-9_]的缩写形式, \s 可以用来表示空格字符。这些特殊字符的大写版本表示不匹配。
正则表达式模式 | 匹配的字符串 |
\w+-\d+ | 31dwq-223(一个由字母数字组成的字符串和一串由一个连字符分隔的数字) |
[A-Za-z]\w* | 第一个字符是字母;其余字符可以是字母或者数字的组合(如果有)。 |
8. 使用圆括号指定分组当使用正则表达式时,一对圆括号可以实现以下任意一个(或者两个)功能:
• 对正则表达式进行分组;
• 匹配子组。
正则表达式模式 | 匹配的字符串 |
\d+(.\d*)? | 表示简单的浮点数;匹配任何十进制数字,后面接一个小数点和零个或者多个十进制数字,例如:“0.004”,“2”,“75.” |
9. 扩展表示法:它们是以问号开始(?…)。只有(?P<name>) 表述一个分组匹配。所有其他的都没有创建一个分组。
正则表达式模式 | 匹配的字符串 |
(?:\w+\.)* | 以句点作为结尾的字符串,例如“google.”、“twitter.”、“facebook.”,但是这些匹配不会保存下来供后续的使用和数据检索 |
(?#comment) | 此处并不做匹配,只是作为注释 |
(?=.com) | 如果一个字符串后面跟着“.com”才做匹配操作,并不使用任何目标字符串 |
(?!.net) | 如果一个字符串后面不是跟着“.net”才做匹配操作 |
(?<=800-) | 如果字符串之前为“800-”才做匹配,假定为电话号码, 同样,并不使用任何输入字符串 |
(?<!192\.168\.) | 如果一个字符串之前不是“192.168.”才做匹配操作,假定用于过滤掉一组 C 类 IP 地址 |
(?(1)y|x) | 如果一个匹配组 1(\1)存在, 就与 y 匹配;否则,就与 x 匹配 |