不可打印的字符

不可打印字符


我们可以使用特殊字符序列将不可打印的字符放入正则表达式中。使用\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字符。应用程序可以使用代码页中的字符索引或其Unicode代码指向的最后5位来形成ASCII控制字符。或者,应用程序可能只是翻转位0x40。从\c@到\c_的任一种方式都将匹配控制字符0x00到0x1F。但是\c*可能与换行符或字母j相匹配。*是ASCII表中的字符0x2A,因此低5位为0x0A,而翻转位0x40则为0x6A。在支持\cA到\cZ匹配控制字符的应用程序中,在\c之后,元字符确实确实失去了其含义。原始的JGsoft风格,.NET和XRegExp做的更好。他们将\c之后的字母以外的其他内容都视为错误。

在XML Schema正则表达式和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将与euro符号匹配。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标准规定,以反斜杠开头的“普通”字符的行为是“undefined”。  

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

查看笔记

扫码一下
查看教程更方便