Python3 将双反斜杠替换为单反斜杠

7
我需要在Python3中将复杂字符串中的\\替换为\。我知道这个问题已经被问过多次,但大多数情况下都是针对简单字符串的,因此没有一个(被接受的)答案真正适用于复杂字符串。
这也与这个不同,那里的问题可以通过.decode('unicode_escape')来解决,但这种方法对于这个问题不起作用。请参见下文。
假设字符串如下:
my_str = '\\xa5\\xc0\\xe6aK\\xf9\\x80\\xb1\\xc8*\x01\x12$\\xfbp\x1e(4\\xd6{;Z\\x'

直接的方法是:

my_str.replace('\\','\')

这导致:

语法错误:扫描字符串文字时遇到行尾


这个答案建议使用:

my_str.replace('\\\\','\\')

这将导致:
'\\xa5\\xc0\\xe6aK\\xf9\\x80\\xb1\\xc8*\x01\x12$\\xfbp\x1e(4\\xd6{;Z\\x'

所以,没有变化。


这个答案建议:

b = bytes(my_str, encoding='utf-8')
b.decode('unicode-escape')

但是对于这样一个复杂的字符串,这种方法行不通:

UnicodeDecodeError:“unicodeescape”编解码器无法解码49-50位置的字节:截断的\xXX转义


使用 decode(如此处建议 here)的结果为:

my_str.decode('unicode_escape')

AttributeError: 'my_str'对象没有'decode'属性。
使用unicode_escape进行编码和解码会返回完全不同的字符串(可能是因为使用了utf-16,但utf-8会出错,如上所述。此外,例如latin1无法正常工作):
my_str.encode('utf-16').decode('unicode_escape')
'ÿþ\\\x00x\x00a\x005\x00\\\x00x\x00c\x000\x00\\\x00x\x00e\x006\x00a\x00K\x00\\\x00x\x00f\x009\x00\\\x00x\x008\x000\x00\\\x00x\x00b\x001\x00\\\x00x\x00c\x008\x00*\x00\x01\x00\x12\x00$\x00\\\x00x\x00f\x00b\x00p\x00\x1e\x00(\x004\x00\\\x00x\x00d\x006\x00{\x00;\x00Z\x00\\\x00x\x00'


your_text.replace('\\', '') 能起作用吗?实际上你并没有双重文字反斜杠... - Jon Clements
没错,这个可以工作。但是一旦我把 '' 作为第二个参数,它就不能工作了。 - black
2
我猜你其实不需要这么做。通常,人们会打印出值并看到双反斜杠,但那只是Python用来明确告诉你字符串中有一个单反斜杠的方式。你能否更详细地说明这个字符串来自哪里,以及为什么要更改它? - Ned Batchelder
@black 给我们更多的细节,我们可以帮助您正确地解决问题。或者加入我们在 Freenode 上的 #python IRC 频道,我们可以进行实际讨论并找到问题的根源。 - Ned Batchelder
但是对于如此复杂的字符串,这种方法行不通:问题在于该字符串以一个反斜杠后跟一个小写x结尾。所描述的问题是将(反斜杠、小写x、两个十六进制数字)序列替换为相应的转义Unicode代码点;但是当十六进制数字缺失时,你想要做什么 - Karl Knechtel
2个回答

8
仔细看这个字符串,它们都是单斜杠。
In [26]: my_str[0]
Out[26]: '\\'

In [27]: my_str[1]
Out[27]: 'x'

In [28]: len(my_str[0])
Out[28]: 1

my_str.replace('\\','\')无法正常工作,因为此处的令牌是',它转义了'并等待另一个关闭'
请使用my_str.replace('\\', '')代替。


更新:经过几天的研究,我发现以下讨论也可能有所帮助。如果一个具有转义字符('\\x''\\u')的字符串的意图最终是十六进制/unicode字面量,则可以通过escape_decode进行解码。

import codecs
print(len(b'\x32'), b'\x32')                # 1 hex literal, '\x32' == '2'
print(len(b'\\x32'), b'\\x32')              # 4 chars including escapes
print(codecs.escape_decode('\\x32', 'hex')) # chars->literal, 4->1

# 1 b'2'
# 4 b'\\x32'
# (b'2', 4)

s = '\\xa5\\xc0\\xe6aK\\xf9\\x80\\xb1\\xc8*\x01\x12$\\xfbp\x1e(4\\xd6{;Z'
ed, _ = codecs.escape_decode(s, 'hex')
print(len(s), s)
print(len(ed), ed)

# 49 \xa5\xc0\xe6aK\xf9\x80\xb1\xc8*$\xfbp(4\xd6{;Z
# 22 b'\xa5\xc0\xe6aK\xf9\x80\xb1\xc8*\x01\x12$\xfbp\x1e(4\xd6{;Z'

1
如果您这样做:
s  = '\\xa5\\xc0\\xe6aK\\xf9\\x80\\xb1\\xc8*\x01\x12$\\xfbp\x1e(4\\xd6{;Z\\x'

s = s.replace('\\','\')

print(s)

你得到
 File "main.py", line 3
    s = s.replace('\\','\')
                         ^
SyntaxError: EOL while scanning string literal

因为在'\'中,反斜杠'\'转义了单引号'。你的字符串没有闭合。
s中没有任何双反斜杠'\\',它只是将其显示为这样,以便于区分用于转义内容的'\\'
如果你print(s),你会得到\xa5\xc0\xe6aK\xf9\x80\xb1\xc8*$\xfbp(4\xd6{;Z\x

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接