原生字符串标识

比如,你用标准regex库来写一个正则表达式,但正则表达式中的反斜杠’\’其实却是一个“转义(escape)”操作符(用于特殊字符),这相当令人讨厌。考虑如何去写“由反斜杠隔开的两个词语”这样一个模式(\w\\w):

string s = "\\w\\\\\\w";  // 希望它是对的(译注:不直观、不美观,且容易出错)

请注意,在正则表达式和普通C++字符串中,各自都需要使用连续两个反斜杠来表示反斜杠本身。然而,假如使用C++11的原生字符串,反斜杠本身仅需一个反斜杠就可以表示。因而,上述的例子简化为:

string s = R"(\w\\\w)";  // 这次百分百正确

引发原生字符串标识提议的是这样一个“惊天地泣鬼神”的例子:

"('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|"  // 这五个反斜杠是否正确?
      // 即使是专家,也很容易被这么多反斜杠搞得晕头转向

R”(…)”记法相比于”…”会有一点点的冗长,但为了不必使用烦琐的“转义(escape)”符号,“多一点”是必要的。

那么,如何将双引号‘”‘本身放到原生字符串里呢?只要它不是正好跟在右括弧’)’之后,那么非常简单:

R"("quoted string")"   // 这个字符串是 “quoted string”

但是,假如我们偏要在原生字符串中表达右括弧后跟双引号 )” 这样一个奇葩组合呢?首先,幸运地是,这种情况一般很少碰到;其次,”(…)”分隔法只不过是默认的分隔语法罢了。通过在“(…)”(…)前后添加显式的自定义分隔号(译注:例如下面例子中的三个星号*),我们还可以创造出任何我们想要的分隔语法。

// 字符串为:"quoted string containing the usual terminator (")"
R"***("quoted string containing the usual terminator (")")***"

在右括弧之后的字符序列(即:自定义分隔号)必须与左括弧之前的字符序列相同。通过这种方式,我们几乎可以处理任意复杂的模式。

参考:

(翻译:张潇,dabaitu)