快速入门
教程
工具和语言
示例
参考
书评
正则表达式教程
简介
目录
特殊字符
不可打印字符
正则表达式引擎内部
字符类
字符类减法
字符类交集
简写字符类
单词边界
交替
可选项
重复
分组和捕获
反向引用
反向引用,第 2 部分
命名组
相对反向引用
分支重置组
自由间距和注释
Unicode
模式修饰符
原子分组
占有量词
前瞻和后顾
环视,第 2 部分
将文本排除在匹配之外
条件
平衡组
递归
子例程
无限递归
递归和量词
递归和捕获
递归和反向引用
递归和回溯
POSIX 方括号表达式
零长度匹配
继续匹配
本网站上的更多内容
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用程序和语言
正则表达式示例
正则表达式参考
替换字符串参考
书评
可打印 PDF
关于本网站
RSS 提要和博客
RegexBuddy—Better than a regular expression tutorial!

不可打印字符

你可以使用特殊字符序列在正则表达式中放置不可打印字符。使用 \t 匹配制表符(ASCII 0x09),使用 \r 匹配回车(0x0D),使用 \n 匹配换行(0x0A)。更奇特的不可打印字符有 \a(响铃,0x07),\e(转义,0x1B)和 \f(换页,0x0C)。请记住,Windows 文本文件使用 \r\n 作为行尾,而 UNIX 文本文件使用 \n

在某些版本中,\v 匹配垂直制表符(ASCII 0x0B)。在其他版本中,\v 是一个简写,它匹配任何垂直空白字符。其中包括垂直制表符、换页符和所有换行符。Perl 5.10、PCRE 7.2、PHP 5.2.4、R、Delphi XE 及更高版本将其视为简写。早期版本将其视为不必要转义的文字 v。最初,JGsoft 版本 仅使用 \v 匹配垂直制表符。JGsoft V2 使用 \v 匹配任何垂直空白字符。

许多正则表达式风格还支持令牌 \cA\cZ,以插入 ASCII 控制字符。反斜杠后面的字母始终是小写 c。第二个字母是大写字母 A 到 Z,表示 Control+A 到 Control+Z。这些等效于 \x01\x1A(26 十进制)。例如,\cM 匹配回车符,就像 \r\x0D\u000D 一样。大多数风格允许第二个字母是小写,含义没有差异。只有 Java 要求 A 到 Z 为大写。

不建议在 \c 后使用除字母之外的字符,因为不同应用程序之间的行为不一致。有些允许 \c 后出现任何字符,而另一些则允许 ASCII 字符。应用程序可能会取代码页中该字符索引的最后 5 位或其 Unicode 代码点来形成 ASCII 控制字符。或者应用程序可能只翻转位 0x40。无论哪种方式,\c@\c_ 都将匹配控制字符 0x00 到 0x1F。但 \c* 可能匹配换行符或字母 j。星号在 ASCII 表中是字符 0x2A,因此低 5 位是 0x0A,而翻转位 0x40 会得到 0x6A。在支持 \cA\cZ 匹配控制字符的应用程序中,元字符确实会在 \c 后立即失去其含义。最初的 JGsoft 风格、.NETXRegExp 更加明智。它们将 \c 后除字母之外的任何内容视为错误。

XML 模式正则表达式XPath 中,\c简写字符类,它匹配 XML 名称中允许的任何字符。

JGsoft 风格 最初将 \cA\cZ 视为控制字符。但 JGsoft V2 将 \c 视为 XML 简写。

如果您的正则表达式引擎支持 Unicode,您可以使用 \uFFFF\x{FFFF} 来插入 Unicode 字符。欧元货币符号占据 Unicode 代码点 U+20AC。如果您无法在键盘上键入它,您可以使用 \u20AC\x{20AC} 将其插入正则表达式中。有关 匹配 Unicode 代码点 的更多详细信息,请参阅 Unicode 教程部分。

如果您的正则表达式引擎使用 8 位代码页而不是 Unicode,那么如果您知道字符集中的位置,则可以在正则表达式中包含任何字符。在 Latin-1 字符集中,版权符号是字符 0xA9。因此,要搜索版权符号,可以使用 \xA9。搜索制表符的另一种方法是使用 \x09。请注意,需要前导零。在 Tcl 8.5 及更早版本中,您必须小心此语法,因为 Tcl 过去会使用 \x 后的所有十六进制字符,并将最后 4 个字符视为 Unicode 代码点。因此,\xA9ABC20AC 将匹配欧元符号。Tcl 8.6 仅将前两个十六进制数字作为 \x 的一部分,就像所有其他正则表达式风格一样,因此 \xA9ABC20AC 匹配 ©ABC20AC

换行符

\R 是一种特殊转义字符,它匹配任何换行符,包括 Unicode 换行符。它的特殊之处在于,它将 CRLF 对待为不可分割的。如果 \R 的匹配尝试始于字符串中的 CRLF 对之前,那么单个 \R 将匹配整个 CRLF 对。\R 不会回溯以仅匹配 CRLF 对中的 CR。因此,虽然 \R 可以匹配单个 CR 或单个 LF,但 \R{2}\R\R 无法匹配单个 CRLF 对。第一个 \R 匹配了整个 CRLF 对,没有留下任何内容供第二个匹配。

或者至少,这就是 \R 应该如何工作的。它在 JGsoft V2、Ruby 2.0 及更高版本、Java 8 以及 PCRE 8.13 及更高版本中就是这样工作的。Java 9 引入了一个错误,允许 \R\R 匹配单个 CRLF 对。PCRE 7.0 到 8.12 有一个错误,允许 \R{2} 匹配单个 CRLF 对。Perl 有一个不同的错误,结果相同。

请注意,\R 仅向前查找以匹配 CRLF 对。正则表达式 \r\R 可以匹配单个 CRLF 对。在 \r 消耗了 CR 之后,剩余的单个 LF 是 \R 匹配的有效换行符。此行为在所有版本中都是一致的。

八进制转义字符

许多应用程序还支持八进制转义,形式为 \0377\377,其中 377 是字符在字符集中的位置的八进制表示(本例中为十进制 255)。在反斜杠后允许或需要多少个八进制数字、是否需要或不允许前导零以及 \0 是否在没有其他数字的情况下匹配 NULL 字节,这在不同正则表达式风格之间差异很大。在某些风格中,这会导致复杂情况,因为 \1\77 可以是八进制转义 1 到 63(十进制)或 反向引用 1 到 77(十进制),具体取决于正则表达式中有多少个 捕获组。因此,强烈建议不要在正则表达式中使用这些八进制转义。改用十六进制转义。

Perl 5.14、PCRE 8.34、PHP 5.5.10 和 R 3.0.3 支持八进制转义的新语法 \o{377}。您可以在大括号之间输入任意数量的八进制数字,可以有或没有前导零。它不会与反向引用混淆,并且随后的文字数字由闭合大括号清晰分隔。请务必仅在大括号之间放置八进制数字。在 Perl 中,\o{whatever} 不是错误,而是匹配 NULL 字节。

JGsoft 风格 最初支持八进制转义,形式为 \0377。JGsoft V2 支持 \o{377},并将 \0377 视为错误。

正则表达式语法与字符串语法

许多编程语言在其源代码中文字字符串的语法中支持类似的非打印字符转义。然后,编译器在将字符串传递给正则表达式引擎之前,将这些转义转换为其实际字符。如果正则表达式引擎不支持相同的转义,则当正则表达式指定为源代码中的文字字符串时,与从文件读取或从用户输入接收的正则表达式相比,这会导致行为上的明显差异。例如,POSIX 正则表达式 不支持任何这些转义。但是 C 编程语言确实支持字符串文字中的 \n\x0A 等转义。因此,在使用 POSIX 库开发 C 中的应用程序时,只有当您将正则表达式作为字符串文字添加到源代码时,\n 才被解释为换行符。然后,编译器解释 \n,正则表达式引擎看到一个实际的换行符字符。如果您的代码从文件中读取相同的正则表达式,则正则表达式引擎会看到 \n。根据实现的不同,POSIX 库会将其解释为文字 n 或错误。实际的 POSIX 标准规定,反斜杠前接“普通”字符的行为是“未定义”。

Python 3.2 及更早版本中存在类似问题,带有 Unicode 转义 \uFFFF。自 Python 添加 Unicode 支持以来,Python 就支持此语法作为(Unicode)字符串文字的一部分。但 Python 的 re 模块 仅从 Python 3.3 开始支持 \uFFFF。在 Python 3.2 及更早版本中,将正则表达式作为文字(Unicode)字符串添加到 Python 代码时,\uFFFF 起作用。但是,当 Python 3.2 脚本从文件或用户输入中读取正则表达式时,\uFFFF 会按字面意思匹配 uFFFF,因为正则表达式引擎将 \u 视为转义文字 u