每周技巧 #64:原始字符串字面量
本节阅读量:本文翻译自 Abseil 官网的 Tip of the Week #64: Raw String Literals。
原文最初作为 totw/64 发布于 2013 年 12 月 9 日。
更新于 2017 年 10 月 23 日。
"(?:\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*')"; – 一只猫从键盘上走过……或者也许是狐狸叫声……不,其实只是现实 C++ 代码里发现的一段高度转义的正则表达式。
你很可能曾经因为转义问题,在 C++ 中很难让正则表达式被正确理解。同样,在单元测试里嵌入 Protobuf 文本格式或 JSON 数据时,为了保留引号和换行,你大概也烦过。当你不得不使用大量转义(更糟时,是多层转义)时,代码清晰度会急剧下降。
幸运的是,C++11 有一个新特性可以消除这种转义需求:原始字符串字面量。
原始字符串字面量格式
原始字符串字面量有如下特殊语法:
|
|
tag 是一个最多 16 个字符的序列(空 tag 也可以,而且很常见)。"tag( 之后、随后第一次出现的 )tag" 之前的字符,会被按字面值用作字符串字面量的内容。tag 可以包含除括号、反斜杠和空白字符之外的任何字符。
看看区别:
|
|
对比:
|
|
特殊情况
注意,缩进规则和原始字符串字面量可以包含换行这一事实结合起来,会让你在如何缩进原始字符串块的第一行上陷入尴尬选择。因为文本 protobuf 会忽略空白,在这种情况下可以通过添加一个前导换行(解析器会忽略)来避免这个问题,但并不是所有原始字符串用途都这么宽容。
当字符串中恰好出现序列 )",从而不能把它当作结束分隔符时,非空 tag 很有用:
|
|
结论
对我们大多数人来说,原始字符串字面量当然不是每天都会用到的工具,但有些时候,善用这个新语言特性会提升可读性。所以下次当你挠头思考到底需要两个 \\ 还是四个时,试试原始字符串字面量。即使正则表达式仍然很难,你的读者也会感谢你:
|
|