本节书摘来自异步社区《正则表达式经典实例(第2版)》一书中的第2章,第2.2节,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.2 匹配不可打印字符
问题描述
匹配一个包含下列ASCII控制字符的字符串:振铃符(bell)、转义符(escape)、换页符(form feed)、换行符(line feed)、回车符(carriage return)、水平制表符(horizontal tab)和垂直制表符(vertical tab)。这些字符的十六进制ASCII编码分别是07、1B、0C、0A、0D、09、0B。
下面演示了转义序列的用法,以及如何以十六进制编码代表字符。
解决方案
\a\e\f\n\r\t\v
正则选项:无
正则流派:.NET、Java、PCRE、Python、Ruby
\x07\x1B\f\n\r\t\v
正则选项:无
正则流派:.NET、Java、JavaScript、Python、Ruby
\a\e\f\n\r\t\x0B
正则选项:无
正则流派:.NET、Java、PCRE、Perl、Python、Ruby
讨论
这7个最常用的ASCII控制字符拥有专门的转义序列。它们都包含一个反斜杠与一个字母。这与在许多编程语言中用于字符串字面文本的语法是相同的。表2-1给出了常用的不可打印字符以及它们的表示方法。
在Perl 5.10及以后版本和PCRE 7.2及以后版本中,‹v›的确匹配垂直制表符。不过在这些流派中‹v›实际上匹配所有垂直空白,包括垂直制表符、换行符以及Unicode行和段落分隔符。因此,对于Perl和PCRE需要使用其他字符表示垂直制表符。
JavsScript不支持‹a›和‹e›。我们需要其他的办法。这些控制字符以及在下面的小节中会给出的替代语法,均可以在正则表达式中的字符组之内和之外同等地使用。
不可打印字符的变体表示
26个控制字符
下边是与本例先前相同的7个ASCII控制字符的另一种匹配方法:
\cG\x1B\cL\cJ\cM\cI\cK
正则选项:无
正则流派:.NET、Java、JavaScript、PCRE、Perl、Ruby 1.9
使用从‹cA›到‹cZ›,可以匹配在ASCII表中占据了第1~26位的26个控制字符。其中的c必须是小写的。在大多数流派中,c之后的字母是不区分大小写的。我们推荐始终使用大写字母,因为Java这样要求。
如果你已经习惯在终端系统上通过按Ctrl键加上一个字符来输入控制符号的话,这种语法会比较容易。在终端上,Ctrl+H会发送一个回车。而在正则表达式中,‹cH›会匹配一个回车。
Python和Ruby 1.8中的经典Ruby引擎并不支持这种语法。而Ruby 1.9中的Oniguruma引擎则支持这种语法。
在ASCII表中第27位的转义控制字符就超出了英语字母表的范围,因此我们会在正则表达式中使用‹x1B›来表示它。
7位字符集
下面是另一种匹配我们列出的这7个常见控制字符的方法:
\x07\x1B\x0C\x0A\x0D\x09\x0B
正则选项:无
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
一个小写的x后跟两个大写十六进制数字可以匹配ASCII字符集中的一个字符。图2-1给出了在完整ASCII字符集中从‹x00›到‹x7F›组合所匹配的每个字符。在该图中,第一个十六进制数字从左边向下排列,而第二个数字则在第一行从左向右排列。
从‹x80›到‹xFF›会匹配哪些字符则要取决于你的正则引擎会如何解释它们,以及你的目标文本使用哪种代码页编码。我们推荐你不要使用‹x80›到‹xFF›。作为替代,应该使用在实例2.7中描述的Unicode码位记号。
如果使用的是Ruby 1.8,或者在编译PCRE时没有使用UTF-8支持,就不能使用Unicode码位。Ruby 1.8和不带UTF-8的PCRE是8位的正则引擎。它们对于文本编码和多字节字符是完全不支持的。在这些引擎中,‹xAA›只会简单地匹配字节0xAA,而不去管0xAA所表示的是哪个字符,或者0xAA是否属于某个多字节字符的一部分。