为什么Python的原始字符串文字不能以单个反斜杠结尾?

时间:2009-03-15 12:54:54

标签: python string literals rawstring

技术上,任何奇数个反斜杠,如the docs

中所述
>>> r'\'
  File "<stdin>", line 1
    r'\'
       ^
SyntaxError: EOL while scanning string literal
>>> r'\\'
'\\\\'
>>> r'\\\'
  File "<stdin>", line 1
    r'\\\'
         ^
SyntaxError: EOL while scanning string literal

似乎解析器可以将原始字符串中的反斜杠视为常规字符(不是原始字符串的全部内容吗?),但我可能错过了一些明显的东西。 TIA!

12 个答案:

答案 0 :(得分:109)

我在粗体突出显示的部分中解释了原因:

  

字符串引号可以使用a进行转义   反斜杠,,但反斜杠仍然存在   在字符串中;例如,r"\""是一个   有效的字符串文字由两个组成   字符:反斜杠和双精度   引用; r"\"不是有效字符串   文字(即使是原始字符串也不能结束   在奇数个反斜杠中)。   具体来说,原始字符串不能结束   在一个反斜杠中(因为   反斜杠会逃避以下情况   引用字符)。还要注意一个   单反斜杠后跟换行符   被解释为那两个字符   作为字符串的一部分,而不是一行   延续。

所以原始字符串不是100%原始的,还有一些基本的反斜杠处理。

答案 1 :(得分:74)

关于python的原始字符串的整个误解是大多数人认为反斜杠(在原始字符串中)只是一个普通字符,就像所有其他人一样。它不是。要理解的关键是这个python的教程序列:

  

当存在“ r ”或“ R ”前缀时,   反斜杠包含在字符串中而没有更改,所有   反斜杠留在字符串

因此反斜杠后面的任何字符都是原始字符串的一部分。一旦解析器输入一个原始字符串(非unicode one)并遇到一个反斜杠,它就会知道有2个字符(反斜杠和后面跟一个字符)。

这样:

  

r'abc \ d'包含 a,b,c,\,d

     

r'abc \'d'包含 a,b,c,\,',d

     

r'abc \''包含 a,b,c,\,'

  

r'abc \'包含 a,b,c,\,',但现在没有终止引用。

最后一个案例显示,根据文档现在,解析器无法找到结束引用,因为您在上面看到的最后一个qoute是字符串的一部分即。反斜杠不能在这里持续,因为它会'吞噬'字符串结束字符。

答案 2 :(得分:19)

就是这样!我认为它是python中的一个小缺陷!

我认为这不是一个很好的理由,但绝对不能解析;用\作为最后一个字符来解析原始字符串真的很容易。

如果你允许\成为原始字符串中的最后一个字符,那么你将无法将“置于一个原始字符串中。看来python似乎允许”而不是允许\作为最后一个字符

然而,这不应该造成任何麻烦。

如果您担心无法轻松编写c:\mypath\等Windows文件夹路径,请不要担心,因为您可以将它们表示为r"C:\mypath",如果您需要附加一个子目录名称,不要使用字符串连接,因为它不是正确的方法!使用os.path.join

>>> import os
>>> os.path.join(r"C:\mypath", "subfolder")
'C:\\mypath\\subfolder'

答案 3 :(得分:14)

另一个技巧是使用chr(92),因为它的计算结果为“\”。

我最近不得不清理一串反斜杠,以下是诀窍:

CleanString = DirtyString.replace(chr(92),'')

我意识到这并没有关注“为什么”,但该线程吸引了许多寻求解决当前问题的人。

答案 4 :(得分:10)

为了让你用斜杠结束原始字符串,我建议你可以使用这个技巧:

>>> print r"c:\test"'\\'
test\

答案 5 :(得分:8)

因为原始字符串中允许使用\“。然后它不能用于标识字符串文字的结尾。

为什么不在遇到第一个“?

时停止解析字符串文字

如果是这种情况,那么\“将不允许在字符串文字中。但它是。

答案 6 :(得分:4)

为什么r'\'语法不正确的原因是虽然字符串表达式是raw,但使用的引号(单引号或双引号)总是必须转义,因为它们会标记引号的结尾。因此,如果您想在单引号字符串中表达单引号,除了使用\'之外别无他法。同样适用于双引号。

但你可以使用:

'\\'

答案 7 :(得分:2)

另一个用户已经删除了他们的答案(不确定他们是否想要被记入),这表明Python语言设计者可以通过使用相同的解析规则并将转义字符扩展为原始形式来简化解析器设计作为事后的想法(如果字面被标记为原始的)。

我认为这是一个有趣的想法,并将其作为后代的社区维基包含在内。

答案 8 :(得分:1)

从C开始,我很清楚单个\作为转义字符,允许您将特殊字符(如换行符,制表符和引号)放入字符串中。

确实不允许\作为最后一个字符,因为它会逃脱“并使解析器窒息。但正如之前所指出的那样\是合法的。

答案 9 :(得分:1)

  

尽管有它的作用,即使是原始字符串也不能以单一形式结束   反斜杠,因为反斜杠会转义以下引号   你仍然必须逃避周围的引用字符   将它嵌入字符串中。也就是说,r“... \”不是有效的字符串   literal - 原始字符串不能以奇数个反斜杠结尾   如果需要使用单个反斜杠结束原始字符串,则可以使用   两个并切掉第二个。

答案 10 :(得分:0)

一些提示:

1)如果你需要操纵路径的反斜杠,那么标准的python模块os.path就是你的朋友。例如:

  

os.path.normpath( 'C:/ folder1中/')

2)如果你想在其中构建带有反斜杠的字符串,但在字符串的END处没有反斜杠,则原始字符串是你的朋友(在你的文字字符串之前使用'r'前缀)。例如:

r'\one \two \three'

3)如果你需要在变量X中用反斜杠作为字符串的前缀,那么你可以这样做:

X='dummy'
bs=r'\ ' # don't forget the space after backslash or you will get EOL error
X2=bs[0]+X  # X2 now contains \dummy

4)如果你需要在结尾创建一个带反斜杠的字符串,那么结合提示2和3:

voice_name='upper'
lilypond_display=r'\DisplayLilyMusic \ ' # don't forget the space at the end
lilypond_statement=lilypond_display[:-1]+voice_name

现在lilypond_statement包含"\DisplayLilyMusic \upper"

万岁蟒蛇! :)

n3on

答案 11 :(得分:0)

我遇到了这个问题,发现了部分解决方案,在某些情况下是好的。尽管python无法以单个反斜杠结束字符串,但可以将其序列化并保存在文本文件中,并以单个反斜杠结尾。因此,如果您需要在计算机上保存带有单个反斜杠的文本,则可以:

x = 'a string\\' 
x
'a string\\' 

# Now save it in a text file and it will appear with a single backslash:

with open("my_file.txt", 'w') as h:
    h.write(x)

顺便说一句,如果您使用python的json库转储json,它将无法使用json。

最后,我使用Spyder,我注意到,如果我在Spider的文本编辑器中通过在变量资源管理器中双击其名称来打开该变量,则该变量将带有一个反斜杠,并且可以通过这种方式复制到剪贴板中。 (对于大多数需求不是很有帮助,但对于某些需求而言。)。