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

it_*_*ure 0 python

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

该文件可以读取,但起初我写道file:

file='D:\tdx\vipdoc\szf10\300383.Txt'
Run Code Online (Sandbox Code Playgroud)

我不能读它 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'
Run Code Online (Sandbox Code Playgroud)

在不使用的情况下我该怎么办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是一个字符串变量,我现在该如何修复它?

Say file不是字符串文字但是从代码的另一部分传递给我的代码,我无法修复使用正确的格式但仍希望能够使用文件名.

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

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

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

>>> 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'
Run Code Online (Sandbox Code Playgroud)

在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)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 7

由于您的"已损坏"文件名实际上并不包含\字符,因此您也无法替换这些字符.你有一个ASCII 9 TAB字符,而不是两个单独的字符\t:

>>> len('\t')
1
>>> '\' in '\t'
False
Run Code Online (Sandbox Code Playgroud)

你必须尝试"修复"破损的绳子; 这不是万无一失的,但你可以创建一个替换表来处理常见的转义序列.对于文件名,它一般不处理回车,制表符或换页字符无论如何,这是完全可行的.

Python字符串文字仅支持有限数量的单字母\转义序列; 请参阅Python字符串文字文档:

\a  ASCII Bell (BEL)     
\b  ASCII Backspace (BS)     
\f  ASCII Formfeed (FF)  
\n  ASCII Linefeed (LF)  
\r  ASCII Carriage Return (CR)   
\t  ASCII Horizontal Tab (TAB)   
\v  ASCII Vertical Tab (VT)
Run Code Online (Sandbox Code Playgroud)

我省略了多字符序列,因为这些在定义文字时往往会出错.只需使用转义序列替换这些字符:

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)
Run Code Online (Sandbox Code Playgroud)

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

>>> '\t'.encode('string_escape')
'\\t'
Run Code Online (Sandbox Code Playgroud)

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

>>> '\a'.encode('string_escape')
'\\x07'
Run Code Online (Sandbox Code Playgroud)

所以这种方法并不适合您的需要.

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

import re

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

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

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

通过精心选择的字符范围,上述内容也可以应用于所有不可打印的ASCII字符,并使用一个表达式修复大多数此类损坏的文件名,前提是我们首先应用上述映射来替换未正确处理的代码'string_escape':

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
Run Code Online (Sandbox Code Playgroud)

演示样本输入:

>>> 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'
Run Code Online (Sandbox Code Playgroud)

这应该为你修复大多数这样的破坏文件名.它不会修复\x09,例如,因为它也被替换\\t.

它也无法检测八进制转义码,也无法修复它们.请注意,\300修复为\xc0.这将需要试运行,尝试所有可能的组合,或对输入做出假设.例如,您可以假设\xhh从未发生过\ooo.

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

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

演示:

>>> 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'
Run Code Online (Sandbox Code Playgroud)

什么有用,有什么用,取决于你期望的文件名类型.例如,如果您知道文件名的最后部分总是以6位数字结尾,则可以执行更多操作.

但是,最好的办法是避免完全破坏文件名.