如何在python中转义整个字符串?

2024-06-09 10:08:42 发布

您现在位置:Python中文网/ 问答频道 /正文

file=r'D:\tdx\vipdoc\szf10\300383.Txt'
text=open(file,"r").read()

该文件可以读取,但首先我将file写成:

^{pr2}$

我不能把它读作text=open(file,"r").read()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument: 'D:\tdx\x0bipdoc\\szf10\xc0383.Txt'

如果不使用file=r'D:\tdx\vipdoc\szf10\300383.Txt',我该怎么办?在

也许我必须用某种方法转义file的整个字符串?在

问题是:文件一开始就定义了,file现在是一个包含字符串的变量,我只能在程序中调用它,如何在程序中修复它。在

  • 方法1:不能使用file=r'D:\tdx\vipdoc\szf10\300383.Txt'。在
  • 方法2:file='D:\\tdx\\vipdoc\\szf10\\300383.Txt'也不能使用。在

当程序已经在运行时,如果file是一个字符串变量,我现在如何修复它?在

假设file不是字符串文本,而是从代码的另一部分传递给我的代码,我无法修复它以使用正确的格式,但仍然希望能够使用文件名。在

为什么我不能用'D:\tdx\vipdoc\szf10\300383.Txt'替换'D:\\tdx\\vipdoc\\szf10\\300383.Txt' simply with文件.replace("\","\\")`? 在

>>> file="D:\tdx\vipdoc\shf10\300383.Txt"
>>> file.replace("\x5c","\x5c\x5c")  #can't work 
'D:\tdx\x0bipdoc\\\\shf10\xc0383.Txt'

我想把它分成两部分,失败了。在

>>> filename = 'D:\tdx\vipdoc\szf10\300383.Txt'
>>> re.search('(.*?)(\d+\.Txt)',filename).group(1)
'D:\tdx\x0bipdoc\\szf10\xc0'
>>> re.search('(.*?)(\d+\.Txt)',filename).group(2)
'383.Txt'

在Martijn Pieters的帮助下,我在映射中添加'\300':r'\300'来解决这个问题。在

mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\n': r'\n',
       '\r': r'\r', '\t': r'\t', '\v': r'\v','\300':r'\300'}
filename = 'D:\tdx\vipdoc\szf10\300383.Txt'
for char, escaped in mapping.items():
    filename = filename.replace(char, escaped)

Tags: 文件方法字符串text程序txtopenfilename
3条回答

因为您的“断开”文件名实际上并不包含\字符,因此您也无法替换这些字符。您有一个ASCII 9制表符,而不是这两个独立的字符\和{}:

>>> len('\t')
1
>>> '\' in '\t'
False

您必须尝试“修复”断开的字符串;这是非常简单的,但是您可以创建一个替换表来处理公共转义序列。对于通常不处理回车、制表符或formfeed字符的文件名来说,这是完全可行的。在

Python字符串文本只支持有限数量的一个字母\转义序列;请参见Python string literal documentation

^{pr2}$

我省略了多字符序列,因为它们在定义文字时容易出错。只需将这些字符替换为转义序列:

mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\n': r'\n',
           '\r': r'\r', '\t': r'\t', '\v': r'\v'}

for char, escaped in mapping.items():
    filename = filename.replace(char, escaped)

或者,我们可以使用'string_escape'编解码器映射这些字符:

>>> '\t'.encode('string_escape')
'\\t'

但不能将此应用于整个字符串,因为这样会使任何正确转义的反斜杠加倍。此外,对于上面的许多转义码,它将使用\xhh转义序列,而不是

>>> '\a'.encode('string_escape')
'\\x07'

所以这个方法不太适合你的需要。在

对于使用\xhh编码的字符,这些字符更难修复。例如,Windows文件系统很好地支持Unicode代码点。如果你做了一个假设,而不是只使用ASCII码位,那么它就变得更容易了。可以使用正则表达式将其替换为其“转义”版本:

import re

filename = re.sub(r'[\x80-\xff]', lambda m: m.group().encode('string_escape'), filename)

这会将ASCII范围之外的任何字节更改为转义序列:

>>> import re
>>> re.sub(r'[\x80-\xff]', lambda m: m.group().encode('string_escape'), '\xc0')
'\\xc0'

如果我们首先应用上述映射来替换'string_escape'未正确处理的代码,则通过一个表达式修复大多数不可打印的ASCII字符:

def repair_filename(filename):
    mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\v': r'\v'}
    for char, escaped in mapping.items():
        filename = filename.replace(char, escaped)
    filename = re.sub(r'[\x00-\x1f\x7f-\xff]', 
                      lambda m: m.group().encode('string_escape'),
                      filename)
    return filename

示例输入的演示:

>>> def repair_filename(filename):
...     mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\v': r'\v'}
...     for char, escaped in mapping.items():
...         filename = filename.replace(char, escaped)
...     filename = re.sub(r'[\x00-\x1f\x7f-\xff]', 
...                       lambda m: m.group().encode('string_escape'),
...                       filename)
...     return filename
... 
>>> filename = 'D:\tdx\vipdoc\szf10\300383.Txt'
>>> repair_filename(filename)
'D:\\tdx\\vipdoc\\szf10\\xc0383.Txt'

这应该可以为您修复大多数这样的损坏文件名。例如,它不会修复\x09,因为它也被\\t取代。在

它也不能检测出八进制转义码,也不能修复它们。注意,\300被修复为\xc0。这将需要反复试验,尝试所有可能的组合,或对输入进行假设。例如,您可以假设\xhh从未发生过,但是\ooo确实发生了。在

在这种情况下,表达式变成:

filename = re.sub(r'[\x00-\x1f\x7f-\xff]', lambda m: '\\{:o}'.format(ord(m.group())), filename)

演示:

>>> def repair_filename(filename):
...     mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\v': r'\v'}
...     for char, escaped in mapping.items():
...         filename = filename.replace(char, escaped)
...     filename = re.sub(r'[\x00-\x1f\x7f-\xff]', 
...                       lambda m: '\\{:o}'.format(ord(m.group())),
...                       filename)
...     return filename
... 
>>> repair_filename(filename)
'D:\\11dx\\vipdoc\\szf10\\300383.Txt'

什么是有效的和不起作用很大程度上取决于您期望的文件名类型。例如,如果知道文件名的最后部分总是以6位数字结尾,则可以做更多的工作。在

当然,最好的办法是避免完全损坏文件名。在

如果使用''而不是r'',则需要手动转义字符串文本中的每个反斜杠:

filename = 'D:\\tdx\\vipdoc\\szf10\\300383.Txt'

使用r''更简单,因为它禁止将\解释为转义字符,因此{}本身不必转义,当您只希望它作为一个文本斜杠存在时。在

通常不能,因为例如'D:\tdx'\t被解释为制表符。但是,您可以尝试将转义字符转换为类似于原始字符串的内容,但这比首先正确地写入文件名要多。在

相关问题 更多 >