鉴于对Python原始字符串末尾奇数个反斜杠的任意限制引起的困惑,可以说这是一个设计错误或遗留问题,起源于希望拥有更简单的解析器。
虽然可以通过一些变通方法(例如r'C:\some\path' '\\')得到(在Python表示法中)'C:\\some\\path\\'或(直接显示)C:\some\path\),但需要这样做并不直观。为了比较,让我们来看看C++和Perl。
在C++中,我们可以直接使用原始字符串文字语法。
#include <iostream>
int main() {
std::cout << R"(Hello World!)" << std::endl;
std::cout << R"(Hello World!\)" << std::endl;
std::cout << R"(Hello World!\\)" << std::endl;
std::cout << R"(Hello World!\\\)" << std::endl;
}
获取以下输出:
Hello World!
Hello World!\
Hello World!\\
Hello World!\\\
如果我们想在字符串字面值中使用闭合分隔符(上面的
)
),我们甚至可以以临时的方式扩展语法为
R"delimiterString(quotedMaterial)delimiterString"
。例如,
R"asdf(some random delimiters: ( } [ ] { ) < > just for fun)asdf"
会在输出中生成字符串
some random delimiters: ( } [ ] { ) < > just for fun
。(这不是一个很好的使用"asdf"吗!)
在Perl中,这段代码
my $str = q{This is a test.\\};
print ($str);
print ("This is another test.\n");
将输出以下内容:
这是一个测试。\这是另一个测试。
将第一行替换为
my $str = q{This is a test.\};
会导致错误信息:
在main.pl的第1行找不到字符串终止符"}"。
然而,Perl将预定界符\
视为转义字符,并不会阻止用户在结果字符串末尾拥有奇数个反斜杠;例如,要在$str
的末尾放置3个反斜杠\\\
,只需以6个反斜杠结尾代码:my $str = q{This is a test.\\\\\\};
。重要的是,在输入中我们需要将反斜杠加倍,但没有类似Python的看起来不一致的语法限制。
另一种看待这个问题的方式是,这三种语言使用不同的方法来处理转义字符和闭合分隔符之间的解析问题:
- Python:禁止在闭合分隔符之前有奇数个反斜杠;一个简单的解决方法是 `r'stringWithoutFinalBackslash' '\\'`。
- C++:允许在分隔符之间使用几乎任何内容。
- Perl:允许在分隔符之间使用几乎任何内容,但需要将反斜杠连续重复两次。
¹ 自定义的 `delimiterString` 本身不能超过16个字符长,但这几乎不是一个限制。
² 如果你需要分隔符本身,只需用 `\` 进行转义。
然而,公平地与Python进行比较,我们需要承认:(1)C++直到C++11才有这样的字符串字面量,并且以其难以解析而闻名;(2)Perl更难解析。