Skip to content

Latest commit

 

History

History
58 lines (43 loc) · 2.33 KB

64.md

File metadata and controls

58 lines (43 loc) · 2.33 KB

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";