如何在Python中防止特殊字符的自动转义

14
我正在编写一个Python脚本,它接受文件路径作为字符串,解析它们,附加一个命令名称并构建一个列表,然后将其传递给subprocess.Popen()以进行执行。此脚本应处理Unix和Windows文件路径,并最终在两个系统上运行。
当我在Unix下运行时,如果我给出了一个包含转义字符的Windows路径(例如\Users\Administrator\bin),Python将把嵌入的\b解释为退格符。我想防止这种情况发生。
据我所知,没有函数或方法可以将字符串变量表示为原始字符串。 'r'修饰符仅适用于字符串常量。
到目前为止,我能够做到的最接近的是:
winpath = "C:\Users\Administrator\bin" 
winpath = winpath.replace('\b','\\b')
winpathlist = winpath.split('\\') 

此时,winpathlist 应该包含 ['C:','Users','Administrator','bin'],而不是 ['C','Users','Administrator\x08in']
我可以添加额外的 winpath.replace() 调用来处理其他可能出现的转义字符 -- \a\f\n\r\t\v,但不能处理 \x
有没有更符合 Python 风格的方法?

5
你是怎样将值传入字符串中的?在Python中,除非\b出现在字符串字面量中或作为转义字符而被传入字符串中,否则Python不会将其视为转义字符。(另外,正斜杠也可以正常工作。) - Wooble
@Wooble: 现在,它通过doctest进入。>>> myCommandObject.setExcecutablePath('C:\Program Files\cygwin\cdrive\bin')其中myCommandObject包含命令名称(例如'ps'),路径和参数列表。将反斜杠改为正斜杠不是一个选项;我的客户明确表示这就是他想要的。 - poltr1
正如我所说,r仅适用于字符串文字;它不适用于字符串变量。我认为前导r是一个临时的解决方法。无论如何,这是doctest(或其中的一部分): >>> myCommand.setExecutablePath('C:\Program Files\cygwin\cdrive\bin') >>> myCommandList = myCommand.getLaunchList() >>> myCommandList ['C:\\Program Files\\cygwin\\cdrive\\bin\\ps', '-e', '-f'] >>> myCommandList[0].split("\\") ['C:', 'Program Files', 'cygwin', 'cdrive', 'bin', 'ps']现在我添加了replace调用后,不再出现任何错误。 - poltr1
忘了感谢Wooble的帮助和建议。在与我的客户咨询后,他选择将Windows路径测试从doctest中移出,并放到一个单独的文件中。 - poltr1
2个回答

20
如果你的winpath是硬编码的,你可能需要在字符串前加上r,以指示它是一个“原始字符串”
winpath = r"C:\Users\Administrator\bin"

如果无法硬编码winpath,您可以尝试创建一个新字符串,如下所示:
escaped_winpath = "%r" % winpath

(这只是repr(winpath),并不会真正帮到你,因为repr("\bin")是...)

一个解决方案是从头重新构建字符串:你可以在这个链接中找到一个函数示例,但通用的思路是:

escape_dict={'\a':r'\a',
             '\b':r'\b',
             '\c':r'\c',
             '\f':r'\f',
             '\n':r'\n',
             '\r':r'\r',
             '\t':r'\t',
             '\v':r'\v',
             '\'':r'\'',
             '\"':r'\"'}

def raw(text):
    """Returns a raw string representation of text"""
    new_string=''
    for char in text:
        try: 
            new_string += escape_dict[char]
        except KeyError: 
            new_string += char
    return new_string

现在,raw("\bin")会给你返回"\\bin"(而不是"\\x08in")...


我不熟悉repr()。它在2.6中吗?我喜欢这个想法,将来可能会用到它。应客户要求,我删除了replace()的调用。他建议我将Windows路径测试从doctest中移出,并放入单独的文件中。感谢您的建议。 - poltr1

7
您可以通过在字符串文字表示前添加 r 来创建原始字符串。
r"hello\nworld"

变得

"hello\\nworld"

您可以在这里阅读更多相关的内容,此处涉及IT技术。


1
否定。如果我按照您的建议在doctest字符串中加入r,则它将成为字符串的一部分。 - poltr1
@poltr1 错了,“r” 不会变成“r”,它只是定义格式。 - questionto42

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