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

自由间距正则表达式

大多数现代正则表达式风格都支持一种称为自由间距模式的正则表达式语法变体。此模式允许使用更易于人们阅读的正则表达式。在本教程中讨论的风格中,只有 XML 模式POSIXGNU 风格不支持它。纯 JavaScript 也不支持,但 XRegExp 支持。该模式通常通过在正则表达式外部设置选项或标志来启用。对于支持 模式修饰符 的风格,您可以在正则表达式的最开始部分放置 (?x),以使正则表达式的其余部分为自由间距。

在自由间距模式下,正则表达式标记之间的空白将被忽略。空白包括空格、制表符和换行符。请注意,只有标记之间的空白会被忽略。a b c 在自由间距模式下与 abc 相同。但 d\d 不同。前者匹配  d,而后者匹配一个数字。\d 是一个由反斜杠和“d”组成的单个正则表达式标记。用空格分解标记会得到一个转义空格(匹配一个空格)和一个字面“d”。

同样,分组修饰符不能被分解。(?>atomic)(?> ato mic )( ?>ato mic) 相同。它们都匹配相同的 原子组。它们与 (? >atomic) 不同。后者是一个语法错误。?> 分组修饰符是正则表达式语法中的一个单一元素,必须保持在一起。对于所有此类结构都是如此,包括 环视命名组 等。

忽略哪些空格和换行符取决于正则表达式风格。本 教程 中讨论的所有风格都忽略 ASCII 空格、制表符、换行符、回车符和换页符。只有 JGsoft V2Boost 忽略所有 Unicode 空格和换行符。JGsoft V1 几乎忽略了所有,但错过了下一行控制字符(U+0085)。Perl 始终将非 ASCII 空格视为字面值。Perl 5.22 及更高版本忽略非 ASCII 换行符。Perl 5.16 及更低版本将它们视为字面值。Perl 5.18 和 5.20 将未转义的非 ASCII 换行符视为自由间距模式中的错误,以便为开发者提供一个过渡期。

字符类中的自由间距

字符类通常被视为一个标记。[abc][ a b c ] 不同。前者匹配三个字母中的一个,而后者匹配这三个字母或一个空格。换句话说:自由间距模式在字符类中不起作用。字符类中的空格和换行符将包含在字符类中。这意味着在自由间距模式下,你可以使用 [ ] 来匹配一个空格。使用你觉得更易读的。当然,十六进制转义 \x20 也适用。

Java 不会在自由间距模式下将字符类视为单个标记。Java 会忽略字符类内的空格、换行符和注释。因此,在 Java 的自由间距模式下,[abc][ a b c ] 相同。要向字符类中添加空格,你必须使用反斜杠对其进行转义。但即使在自由间距模式下,否定脱字符号也必须紧跟在左括号之后。 [ ^ a b c ] 匹配四个字符中的任何一个 ^abc,就像 [abc^] 所做的那样。如果否定脱字符号位于正确的位置,则 [^ a b c ] 将匹配任何不是 abc 的字符。

Perl 5.26 将字符类中的有限自由间距作为一种选项。 /x 标志仅在字符类外部启用自由间距,就像在 Perl 的早期版本中一样。双重 /xx 标志还使 Perl 5.26 将字符类中未转义的空格和制表符视为自由空格。换行符在字符类中仍然是文字。如果你将 PCRE2_EXTENDED_MORE 标志传递给 pcre2_compile(),则 PCRE2 10.30 支持与 Perl 5.26 相同的 /xx 模式。

Perl 5.26 和 PCRE 10.30 还添加了一个新的 模式修饰符 (?xx),它在字符类内外都启用自由间距。 (?x) 会像以前一样在字符类外部启用自由间距,但也会关闭字符类内的自由间距。 (?-x)(?-xx) 都完全关闭自由间距。

Java 将 ^ 中的 [ ^ a ] 视为文字。即使忽略空格,它们仍然会破坏脱字符号在 Java 中的特殊含义。Perl 5.26 和 PCRE2 10.30 将 ^ 中的 [ ^ a ] 视为 /xx 模式中的否定脱字符号。Perl 5.26 和 PCRE2 10.30 完全忽略自由空格。它们仍然认为脱字符号位于字符类的开头。

自由间距模式中的注释

自由间距模式的另一个功能是 # 字符开始注释。注释一直持续到该行的末尾。从 # 到下一个换行符之间的所有内容都被忽略。大多数风格都不识别任何其他换行符作为注释的结尾,即使它们将其他换行符识别为自由空白或允许 锚点匹配其他换行符。JGsoft V2 是唯一识别所有 Unicode 换行符的风格。Boost 错过了垂直制表符。

XPathOracle 即使具有自由间距模式,也不支持正则表达式中的注释。它们始终将 # 视为一个字面字符。

Java 是唯一在自由间距模式下将 # 视为字符类中注释开头的风格。注释一直持续到该行的末尾,因此可以使用 ] 来关闭注释。所有其他风格都将 # 视为字符类中的字面量。这包括 /xx 模式下的 Perl 5.26。

综上所述,用于匹配有效日期的正则表达式可以通过跨多行编写来阐明

# 匹配 yyyy-mm-dd 格式的 20 世纪或 21 世纪日期
((?:19|20)\d\d)            # 年份(组 1)
[- /.]                     # 分隔符
(0[1-9]|1[012])            # 月份(组 2)
[- /.]                     # 分隔符
(0[1-9]|[12][0-9]|3[01])   # 日期(组 3)

RegexBuddy makes regular expressions more readable with syntax coloring

无自由间距的注释

许多风格还允许你在不使用自由间距模式的情况下向正则表达式添加注释。语法是 (?#comment),其中“comment”可以是你想要的任何内容,只要不包含右括号即可。正则表达式引擎会忽略 (?# 之后的第一个右括号之前的所有内容。

在本教程中讨论的风格中,所有支持自由间距模式中注释的风格(JavaTcl 除外)也支持 (?#comment)。不支持自由间距模式中注释或根本不支持自由间距模式的风格也不支持 (?#comment)