0%

语言高阶-转义字符

一、可打印字符

转义字符的意思是,原本这个字符表达一个意思,而经过转义后,就会表达另一个意思。原本的意思没有什么特别之处(比如说必须是一个普通字符,一个通配符,一个格式控制符),表达出来的另一个意思也同样没有什么特别之处。

那么为什么要存在转义字符?我们可以用另一个字符来表达更多的意思,而不是让一个已经有一个意思的字符,经过转义后来表达另一个意思。但是可悲的是,这并不是现实的,现实是,我们仅有数量不多的可打印字符,而我们却希望表达更多的意思(这点在正则中尤其明显)。事实就是,每一个可打印字符都有了自己的含义,我们所能做到的,就只是复用他们。

上面的说法有些绝对,却是有方法可以缓解这种方式,比如用 Java 中数字编码转义字符,如 \uF890 这种,可以避免复用的尴尬,不过这样又有些不直观,毕竟谁都喜欢写 \n 而不是 \10

二、分类

转义字符的另一个误区是,所有转义字符遵循的规则是相同的。实际上根据转义字符所在的上下文不同,其含义也会发生变化,比如如果一个 . 出现在了 C string 中,那么就是个英文句号,但是如果出现在了正则表达式中,那么就表示匹配任意字符

2.1 ASSIC

ASSIC 主要解决的问题是一些字符并不是可见字符,但是同样需要被记录。比如说换行符 \n 或者颜色控制字符 \e[1;33m 之类的。转义字符将一个可见字符转义来表示一个控制字符。

此外,因为 \ 用来表示转义,那么 \ 本身的含义就没法表示了,所以我们会用 \\ 表示原本的反斜杠 \

2.2 字符串

字符串的问题在于字符串的分界符无法作为字符串的内容,比如说在 C 语言中用 " 来表示字符串的开始和终止,那么字符串内容中的 " 就没有办法正常打印,此时就需要用转义字符 \" 来表示一个普通的双引号。

在 ASSIC 中用普通字符通过转义表达特殊含义的思路,在这里反了过来,在字符串中," 表示特殊的字符串分界符,而 \" 表示普通的双引号字符。

2.3 通配符和正则

这两个是类似的,他们将 * . ? + $ ^ [ ] ( ) { } | \ 变成了更具有含义的功能字符,而对于字符串中原本的字符,就需要用转义字符了。

三、组合

更让人困惑的是,上面介绍的分类并不是完全不重叠的,事实就是,我们常在编程语言中使用正则表达式,那么转义就会变成多重的,比如说下面的例子

"^\\*eshell.*\\*.*$"

这个例子中,首先它是一个编程字符串,所以这个字符串内容是

^\\*eshell.*\\*.*$

然后因为这是一个 ASSIC 字符,所以 \\ 表示的是 \ ,所以进一步处理得到真正的正则表达式:

^\*eshell.*\*.*$

而这种正则中又存在 \* 按照正则的规则,表示的是真正的 * ,所以实际表达是:

* 开头(^\*),紧接 eshell ,而后会匹配任意字符任意长度(.* ),之后紧接 *, 最后以任意字符任意长度结尾(.*$)。