教程 > 正则表达式 > 修饰符 阅读:48

free-spacing 和 注释

Free-Spacing正则表达式


大多数现代正则表达式都支持一种称为Free-Spacing模式的正则表达式语法。此模式允许对正则表达式进行格式化,使人们更容易阅读。在本教程中讨论的正则表达式中,只有XML Schema以及POSIX和GNU不支持它。普通的JavaScript也不支持,但是XRegExp可以。通常通过在正则表达式外部设置选项或标志来启用该模式。我们可以使用模式修饰符的方式,将(?x)放在正则表达式的最开始,以使正则表达式的其余部分可以Free-Spacing。

在Free-Spacing模式下,正则表达式标记之间的空白将被忽略。空白包括空格,制表符和换行符。请注意,仅标记之间的空格被忽略。a b c与free-spacing模式下的abc相同。但是\ d\d不相同。前者匹配d ,而后者匹配一个数字。\ d是由反斜杠和“ d”组成的单个正则表达式令牌。用空格将标记分解会给我们一个转义的空格(与空格匹配)和一个字符“ d”。

同样,分组修饰符也无法分解。(?>atomic)(? ato mic )( ?> ato mic )。它们都匹配相同的原子组。它们与(? >atomic)不同。后者是语法错误。?>在正则表达式中,表示一个组修饰符,它们是一个整体,不可以分割,并且必须保持在一起。所有此类构造(包括lookround命名组等)都是如此。

忽略哪些空格和换行符取决于正则表达式引擎。本教程中讨论的所有样式都忽略ASCII空格,制表符,换行符,回车符和换页符。JGsoft V2和Boost是唯一忽略所有Unicode空格和换行符的。Perl始终将非ASCII空格视为文字。Perl 5.22和更高版本会忽略非ASCII换行符。Perl 5.16和以前的版本将它们视为文字。Perl 5.18和5.20将未转义的非ASCII换行符视为Free-Spacing模式中的错误,从而为开发人员提供了过渡期。

字符类中的Free-Spacing


字符类通常被视为单个标记。[abc][ a b c ] 是不一样的。前者匹配三个字母之一,而后者匹配这三个字母之一或一个空格。换句话说:Free-Spacing模式在字符类中不起作用。字符类中的空格和换行符将包含在字符类中。这意味着在Free-Spacing模式下,我们可以使用\ (反斜杠后面有个空格)或[ ]来匹配单个空格。当然,十六进制转义\ x20也可以正常匹配。 

但是,Java在Free-Spacing模式下不会将字符类视为单个标记。Java确实会忽略字符类中的空格,换行符和注释。因此,在Java的Free-Spacing模式下,[abc][ a b c ]相同。要在字符类中添加空格,我们必须使用反斜杠对其进行转义。但是,即使在Free-Spacing模式下,^也必须紧接在左括号之后。[ ^ a b c ]匹配四个字符^ ,a ,b或c中的任何一个,就和[abc^]一样。将^写到正确的位置,[^ a b c ]匹配不是a ,b或c的任何字符。

Perl 5.26在字符类中提供了有限的Free-Spacing选项。在Perl之前的版本中,/x在字符类之外使用的时候才会激活Free-Spacing模式。两个x的标记 /xx还使Perl 5.26可以将字符类中未转义的空格和制表符视为Free-Spacing。换行符仍然是字符类中的文字。如果将标志PCRE2_EXTENDED_MORE传递给pcre2_compile(),则PCRE2 10.30支持与Perl 5.26相同的/xx模式。

Perl 5.26和PCRE 10.30还添加了一个新的模式修饰符(?xx),该修饰符在字符类内部和外部都能实现Free-Spacing。(?x)像先前介绍的一样对于外部字符类的标记启用Free-Spacing,但对字符类内部则不起作用。(?-x)(?-xx)都完全关闭Free-Spacing。

在Java中将[ ^ a ]中的^仅仅视为一个普通的字符。即使我们设定了要忽略空格,但是它们仍然会破坏Java中^的特殊含义。Perl的5.26和PCRE2 10.30在/xx模式下将[ ^ a ]中的^视为否定插入符。Perl 5.26和PCRE2 10.30完全忽略了Free-Spacing。它们仍然认为^位于字符类的开始。   

Free-Spacing模式中的注释


Free-Spacing模式的另一个功能是使用#字符在正则表达式中增加注释。注释一直到该行的末尾。从#到下一个换行符的所有内容都将被忽略。JGsoft V2是唯一可以识别所有Unicode换行符的样式。 XPath和Oracle即使具有Free-Spacing模式,也不支持正则表达式中的注释。他们总是将#视为文字字符。

Java提供的正则引擎是唯一一个支持在Free-Spacing模式下将#视为字符类中注释开头的。注释将一直运行到该行的末尾,因此我们可以使用[]关闭注释。所有其他正则引擎都将#视为字符类中的普通的字符。其中包括/xx模式下的Perl 5.26 。

将所有内容放在一起,可以通过编写多行来分别注释与有效日期匹配的正则表达式: 

#使用yyyy-mm-dd 格式 匹配21世纪的20th 
(19|20)\d\d                # year (group 1)
[- /.]                     # separator
(0[1-9]|1[012])            # month (group 2)
[- /.]                     # separator
(0[1-9]|[12][0-9]|3[01])   # day (group 3)

没有Free-Spacing模式的注释


许多正则引擎还允许我们在不使用Free-Spacing模式的情况下向正则表达式添加注释。语法为(?#comment),其中“ comment”可以是我们想要的任何形式,只要它不包含右括号即可。正则表达式引擎将忽略(?#之后的第一个右括号之前的所有内容。

在本教程中讨论的各种正则引擎中,所有支持Free-Spacing模式注释的正则引擎(Java和Tcl除外)也都支持(?#comment)。在Free-Spacing模式下不支持注释或完全不支持Free-Spacing模式的正则引擎同样也不支持(?#comment)

查看笔记

扫码一下
查看教程更方便