【发布时间】:2020-07-26 00:26:27
【问题描述】:
我有这段代码可以解析和处理普通的“f-string”模板字符串(请参阅下面的用法部分以获取示例):
from string import Formatter
import sys
_conversions = {'a': ascii, 'r': repr, 's': str}
def z(template, locals_=None):
if locals_ is None:
previous_frame = sys._getframe(1)
previous_frame_locals = previous_frame.f_locals
locals_ = previous_frame_locals
# locals_ = globals()
result = []
parts = Formatter().parse(template)
for part in parts:
literal_text, field_name, format_spec, conversion = part
if literal_text:
result.append(literal_text)
if not field_name:
continue
value = eval(field_name, locals_) #.__format__()
if conversion:
value = _conversions[conversion](value)
if format_spec:
value = format(value, format_spec)
else:
value = str(value)
result.append(value)
res = ''.join(result)
return res
用法:
a = 'World'
b = 10
z('Hello {a} --- {a:^30} --- {67+b} --- {a!r}')
# "Hello World --- World --- 77 --- 'World'"
但是如果模板字符串是这样的就不行了:
z('''
echo monkey {z("curl -s https://www.poemist.com/api/v1/randompoems | jq --raw-output '.[0].content'")} end | sed -e 's/monkey/start/'
echo --------------
''')
它给出了这个错误:
File "<string>", line 1
z("curl -s https
^
SyntaxError: EOL while scanning string literal
如果无法正常运行,我什至愿意从 Python 的源代码中复制代码以使其正常工作。
【问题讨论】:
-
如果你想解析Python代码,你可以看看
astmodule。它允许您像解析常规 f 字符串一样解析字符串:ast.parse('f"Hello, {a} --- {67+b}"')。然后你想要生成的树并按照你想要的方式处理它 -
冒号在格式字符串中的
{}中具有特殊含义。您需要将curl部分拉出到一个单独的变量中,而不是嵌套调用z()。 -
@0x5453 不,它适用于三引号 f 字符串。我检查过。 (其中引用了
:。) -
@ForceBru 您的方法似乎很棒。有没有办法评估解析的
ast的节点?例如_ast.FormattedValue到string? -
@HappyFace,你可以
ast.dump(tree_node)查看每个节点有哪些属性。然后遍历带有ast.NodeVisitor子类的树,并检查每个节点的属性。对于f"{a}",您可以像这样检索字符串a:FormattedValue_node.value.id。详情请见Python's grammar。
标签: python string parsing quoting f-string