繁体   English   中英

Python:打印/编写转义符的意外行为

[英]Python: unexpected behavior with printing/writing escape characters

我正在尝试读取一个文件,其中包含\\\\\\n\\t字符串,并且我想将这些字符串写为\\ ,换行符和tab。 我对re.sub尝试似乎未在我的.py文件中工作,但似乎在解释器中工作。

这是我为实现此目的而编写的功能:

def escape_parser(snippet):
    snippet = re.sub(r"\\", "\\", snippet)
    snippet = re.sub(r"\t", "\t", snippet)
    snippet = re.sub(r"\n", "\n", snippet)

    return snippet

这会导致sre_constants.error: bogus escape (end of line)包含反斜杠替换行时出现sre_constants.error: bogus escape (end of line) ,并且当我注释掉反斜杠行时,似乎没有用制表符或换行符替换文字字符串\\t\\n

我在解释器中玩耍,看看是否可以找到解决方案,但是所有操作都符合我(天真)的期望。

$ python3
Python 3.4.0 (default, Mar 24 2014, 02:28:52) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> test = "for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}"
>>> import re
>>> test = "for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}"
>>> print(re.sub(r"\n", "\n", test))
for(int ${1:i}; $1 < ${2:STOP}; ++$1)
{
    $0
}
>>> print(test)
for(int ${1:i}; $1 < ${2:STOP}; ++$1)
{
    $0
}
>>> test
'for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}'
>>> t2 = re.sub(r"\n", "foo", test)
>>> t2
'for(int ${1:i}; $1 < ${2:STOP}; ++$1)foo{foo\t$0foo}'

至于实际写入文件,我有

使用open(os.path.join(target_path,name),“ w”)为out:out.write(snippet)

尽管我也尝试过使用print(snippet, end="", file=out)

编辑:我看过类似的问题,如Python如何用re.sub()替换反斜杠以及如何将字符串列表写入文件,添加换行符? ,但是这些解决方案并不能很好地发挥作用,如果可能的话,我真的很想使用正则表达式来执行此操作,因为它们似乎比Python的标准字符串处理功能更强大。

Edit2:不确定这是否有帮助,但是我想我将尝试打印该函数中发生的事情:

def escape_parser(snippet):                                                                                                                                                                                       
    print(snippet)                                                                                                                                                                                                
    print("{!r}".format(snippet))                                                                                                                                                                                 

    # snippet = re.sub(r"\\", "\\", snippet)                                                                                                                                                                      
    snippet = re.sub(r"\t", "\t", snippet)                                                                                                                                                                        
    snippet = re.sub(r"\n", "\n", snippet)                                                                                                                                                                        

    print(snippet)                                                                                                                                                                                                
    print("{!r}".format(snippet))                                                                                                                                                                                 

    return snippet

产量

for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}
'for(int ${1:i}; $1 < ${2:STOP}; ++$1)\\n{\\n\\t$0\\n}'
for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}
'for(int ${1:i}; $1 < ${2:STOP}; ++$1)\\n{\\n\\t$0\\n}'

Edit3:按照@BrenBarn的建议,将snippet = re.sub(r"\\\\", "\\\\", snippet)更改为snippet = re.sub(r"\\\\", r"\\\\", snippet)在我的源文件中添加测试字符串会产生

insert just one backslash: \\ (that's it)
"insert just one backslash: \\\\ (that's it)"
insert just one backslash: \\ (that's it)
"insert just one backslash: \\\\ (that's it)"

所以我一定错过了一些明显的事情。 不需要编程许可是件好事。

Edit4:按照Python中字符串中的Process转义序列 ,我将escape_parser更改为:

def escape_parser(snippet):                                                                                                                                                                                                                                                                                                                                             
    print("pre-escaping: '{}'".format(snippet))                                                                                                                                                                   

    # snippet = re.sub(r"\\", r"\\", snippet)                                                                                                                                                                     
    # snippet = re.sub(r"\t", "\t", snippet)                                                                                                                                                                      
    # snippet = re.sub(r"\n", "\n", snippet)                                                                                                                                                                      
    snippet = bytes(snippet, "utf-8").decode("unicode_escape")                                                                                                                                                    

    print("post-escaping: '{}'".format(snippet))                                                                                                                                                                  

    return snippet

在某种意义上是可行的。 我最初的意图是仅替换\\\\\\n\\t ,但这远不止于此,这并不是我想要的。 这是通过该函数运行后的样子(看起来, printwrite工作与此相同。我可能会误认为printwrite不匹配,因为看起来好像我用来检查输出文件的编辑器不会如果进行了新更改,请进行更新。):

pre-escaping: 'for(int ${1:i}; $1 < ${2:STOP}; ++$1)\n{\n\t$0\n}'
post-escaping: 'for(int ${1:i}; $1 < ${2:STOP}; ++$1)
{
    $0
}'
pre-escaping: 'insert just one backslash: \\ (that's it)'
post-escaping: 'insert just one backslash: \ (that's it)'
pre-escaping: 'source has one backslash \ <- right there'
post-escaping: 'source has one backslash \ <- right there'
pre-escaping: 'what about a bell \a like that?'
post-escaping: 'what about a bell  like that?'

在不查看某些数据的情况下很难分辨这是否是您的主要问题,但是一个问题是您需要将第一个替换项更改为:

snippet = re.sub(r"\\", r"\\", snippet)

原因是反斜杠在替换模式中也具有含义(对于组反向引用),因此单个反斜杠不是有效的替换字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM