Tip of the Week #64:原始字符串字面值原文链接
最初在2013-12-09发布为totw/64
作者:Titus Winters (titus@google.com)
更新:2017-10-23
地址:abseil.io/tips/64
"(?:"(?:\\"|[^\"])*"|'(?:\\'|[^'])*')"; ——猫走过键盘?或者是狐狸说的话?不,其实是真实C++代码中有很多转义的正则表达式。
有很大几率,我们都曾因转义问题而很难理解C++的正则表达式。类似地,在单元测试中嵌入文本格式的Protobuf或者JSON时很可能也有怎样保持引号和换号符的问题。需要使用大量的转义(更糟的是多层转义)时,代码清晰度会急剧下降。
幸运的是,有一个C++11新特性可以消除转义,那就是原始字符串字面值(raw string literals)。
格式如下:
R"tag(whatever you want to say)tag"
tag是一段最长不超过16的字符序列(tag为空不仅允许而且常见)。‘“tag(‘之后和后面第一次出现的‘)tag”’之前的字符是字符串字面量的内容,'tag'可以包含除括号、反斜线和空格外的任意字符。
检查下面的不同:
const char concert_17_raw[] =
"id: 17\n"
"artist: \"Beyonce\"\n"
"date: \"Wed Oct 10 12:39:54 EDT 2012\"\n"
"price_usd: 200\n";
对比
const char concert_17_raw[] = R"(
id: 17
artist: "Beyonce"
date: "Wed Oct 10 12:39:54 EDT 2012"
price_usd: 200)";
缩进规则加上字符串字面量可以包含空格,会让怎样缩进字面量的第一行成为尴尬的选择。因为Protobuf文本忽略空格,加(解析器会忽略的)一个起始空行不成问题。但其他情况下的字面量使用就没这么宽宏大量了。
)"
出现在字面量中,因而不能作为结束的分割符时,非空的tag就很有用了。
std::string my_string = R"foo(This contains quoted parens "()")foo";
原始字符串字面量虽然不是日用品,但有时候充分利用这个新特征会增强可读性。下次你绞尽脑汁想知道到底需要两个还是四个\\
时,试着改为使用原始字符串字面值吧。代码阅读者会感激你的,尽管正则表达式本身仍然费解:
R"regexp((?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'))regexp";