Python:使用\ n结尾的字符串进行eval

4

我该如何对带有 \n 的字符串进行 eval 操作?

为什么这样不起作用?

a = eval('"hello \n"')
In [70]: eval("\"hello \n\"")
  File "<string>", line 1
    "hello
          ^
SyntaxError: EOL while scanning string literal

虽然如此

a = "hello \n"

我的使用场景是,通过子进程执行的脚本输出一个字典字符串,我捕获了它的stdout,并希望对其进行eval操作。

'''[
     { "hello": "the description of this is\' \n"}
]'''

2
你知道 eval 是做什么的吗?即使没有换行符,你甚至期望 eval("hello") 做什么呢?你的第二个例子只是将一个字符串赋值给一个变量。 - Cory Kramer
1
我期望它返回一个字符串。注意,这不是eval("hello"),而是eval('"hello"')。 - Har
2
什么是使用案例?为什么需要在字符串上调用eval?为什么它需要有'\n'?如果您分享更多关于问题的信息,我们可以提供更多帮助。 - Amaury Medeiros
1
@Har:eval(pprint.pformat('hello\n')) 可以正常工作,因为 pprint.pformat() 返回结果的漂亮打印字符串而不是将其写入标准输出。 - Martijn Pieters
1
@HarпјҡеҰӮжһңжӮЁеңЁзҲ¶иҝӣзЁӢдёӯдҪҝз”Ёpprint.pprint()并д»Һж ҮеҮҶиҫ“еҮәпјҲstdoutпјүдёӯиҜ»еҸ–пјҢйӮЈд№Ҳ\е’Ңnд№ҹжҳҜеҲҶејҖзҡ„еӯ—з¬ҰпјҢ并且еҸҜд»Ҙдј йҖ’з»ҷeval()гҖӮдҪҶд»Қ然жҳҜдёҚеҘҪзҡ„дё»ж„ҸпјҢеӣ дёәе®ғеҫҲж…ўпјҢиҖҢдё”жңүжӣҙеҘҪзҡ„жӣҝд»Јж–№жі•гҖӮast.literal_eval()йҷҗеҲ¶дәҶеҸӘеҠ иҪҪPythonж–Үеӯ—пјҲе®үе…ЁпјүпјҢдҪҶжҳҜеҜ№дәҺиҝҷз§ҚдәӨжҚўпјҢJSONйҖҹеәҰжӣҙеҝ«гҖӮ - Martijn Pieters
显示剩余8条评论
2个回答

6

您需要转义反斜杠。

>>> eval('"hello \n"')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    "hello
          ^
SyntaxError: EOL while scanning string literal
>>> eval('"hello \\n"')
'hello \n'
>>> print(eval('"hello \\n"'))
hello

>>>

没有这个转义符,Python会看到这段代码(这是一个明显的错误):
"hello 
"

不是期望的代码:

"hello \n"

我对需要转义和不需要转义的内容感到困惑,您能否请澄清一下?例如,如果我有 eval(' "hello's\n" '),它需要更改为 eval(' "hello'\n" '),哪些字符需要转义? - Har
2
如果字符串不是来自字面值,正如您在编辑中提到的那样,您可以查看此问题:https://dev59.com/6G865IYBdhLWcg3wCp9A。 - TigerhawkT3

3

如果您想指定一个带有字面值\n的字符串,您需要将反斜杠进行两倍转义,或者使用原始字符串字面值:

>>> '"hello\\n"'
'"hello\\n"'
>>> r'"hello\n"'
'"hello\\n"'

这样的字符串可以被解释为包含一个字符串字面量的Python表达式:

>>> eval(r'"hello\n"')
'hello\n'

如果你的输出是由子进程输出,并且使用pprint.pprint()来输出值,那么你不仅需要读取该流,而且还需要生成完全有效的Python语法。例如,不要将该输出复制粘贴到Python解释器中,因为这将直接解释转义序列(因此在将其传递给eval()之前)。如果你正在解释器中开发,则可以使用pprint.pformat()来生成带有输出的变量,而不是写入标准输出。
但是,如果你试图使用Python的repr()pprint.pprint()输出在系统之间传递数据,请停止。相反,请使用适当的序列化格式,例如JSON。如果这不可行,至少使用ast.literal_eval()限制代码接受的内容仅限于Python字面量,而不是任意代码(例如'__import__("os").system("rm -rf /"))。

你能否提一下关于pprint.pformat的建议,同时也谈谈关于字符串的编码和解码? 'import("os").system("rm -rf /")真的是一个很好的例子,说明不要把外部字符串当做Python代码来使用 :) - Har

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