Raw String 的巨坑

Raw String的巨坑

众所周知,在编程语言中\字符有着特别的意义.在一个字符串中,\字符会 “转义” 紧接着他的一个字符.,\n会被转义为换行符,\t会被转义为制表符等.这种做法极大地方便了编程,给予了我们一种方便的在字符串字面量(源代码中的固定的量)中表示一个无法输入的或者会破坏语法结构的字符的方式.

但是,在有大量\的情况下我们不希望字符串中的 \ 字符被转义,如在表示地址或正则表达式的时候.因此,很多语言提供了Raw String字面量,Raw string字面量中 \ 字符被视为普通的字符而不是转义符.正如Python文档中描述的:

Both string and bytes literals may optionally be prefixed with a letter ‘r’ or ‘R’; such strings are called raw strings and treat backslashes as literal characters.

字符串与字节字面量都可以以一个r或者R前缀来表示原始字符串.在原始字符串中, \字符被当做普通字符而不是转义符来处理.

正如,Python:

1
2
>>> print(r"asd\nsd\nsd")
asd\nsd\nsd

\n会保持原样输出而不是被替换为换行符.

那么,问题来了:下面的代码会输出什么?

1
print(r"\")

可能看到语法高亮的颜色不太对劲就会让你意识到,Python中输出一个这样的字符串会报错而不是输出一个\字符.Python文档中这样写道:

Even in a raw literal, quotes can be escaped with a backslash, but the backslash remains in the result; for example, r""" is a valid string literal consisting of two characters: a backslash and a double quote; r"" is not a valid string literal (even a raw string cannot end in an odd number of backslashes). Specifically, a raw literal cannot end in a single backslash (since the backslash would escape the following quote character). Note also that a single backslash followed by a newline is interpreted as those two characters as part of the literal, not as a line continuation.

即使在一个原始字面量中,引号仍然会被\字符转义,只不过\字符仍然保留在结果中.: r"""是一个合法的字符串而r""会被认为缺少了一个引号.

这是因为,在原始字面量的处理中,并不是去掉了转义.转义操作仍然在进行,只不过正常情况下 ‘\n’ 会转移成换行符,但是在原始字面量中会转移为字符串\n.在分析那些字符需要转义的时候,编译器(或者说解释器)并不清楚这个字符是否在一个Raw String.编译器会把他标记为需要转义,在之后的步骤中再完成具体的转移操作.但是对于r""这个字符串,在第一步的时候编译器会认为\符号转义了后面的",导致这个字符串的引号数量不匹配,爆出语法错误.

(所以锅还是得丢给编译器)

:上文中编译器指广义上的编译器或解释器等.

感谢群里的小伙伴们,没有你们的帮助和讨论就不会有这篇文章.