【发布时间】:2014-07-23 18:16:03
【问题描述】:
我正在尝试读取一个文件,其中可能包含包含\\、\n 和\t 的字符串,并且我想将它们作为\、换行符和制表符写入另一个文件。我对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),并且当我注释掉反斜杠行时,它似乎不会用制表符或换行符替换文字字符串 \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}'
至于实际写入文件,我有
with open(os.path.join(target_path, name), "w") 作为输出: out.write(sn-p)
虽然我也尝试过使用print(snippet, end="", file=out)。
编辑:我看过类似的问题,如 Python how to replace backslash with re.sub() 和 How to write list of strings to file, adding newlines?,但这些解决方案并不完全奏效,如果可能的话,我真的很想用正则表达式来做这件事,因为它们看起来像'是比 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:根据Process escape sequences in a string in Python,我将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,但这比这更进一步,这并不是我想要的。这是通过函数运行后的情况(看起来print 和write 对这些工作相同。我可能误认为print 和write 不匹配,因为它似乎是我使用的编辑器如果进行了新的更改,则检查输出文件不会更新。):
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?'
【问题讨论】:
-
您的测试字符串不包含任何反斜杠,并且您的替换没有做任何事情,正如您在执行
print(test)时所看到的那样。通过在测试字符串中输入\n,您将在字符串中包含一个实际的换行符,而不是字符串反斜杠-n。 -
它与从源文件中读取的行相同,所以我认为这似乎是在解释器中尝试和测试的最佳候选者,但你是对的。
-
"...因为它们是比 Python 的标准字符串处理函数更强大的工具..." 如果您在用例中不需要这种功能,则不是一个很好的理由,并且 尤其是如果它积极阻碍的话。
-
另外,如果你只是想处理 Python 风格的反斜杠转义,为什么不直接让 Python 反斜杠转义而不是手动处理呢? (如果您特别想要仅取消转义这三个字符,或者您计划构建到 Perl 或 C 反斜杠转义而不是 Python 等,请忽略此注释。)
标签: python regex python-3.x