python - printf 样式格式字符串的解析器
问题描述
有没有一种很好的方法来解析 printf 样式的格式字符串并将各种位(文字文本和具有可处理选项的格式点)作为标准库的一部分,或者作为第三方库失败?我在标准库中找不到一个,而且网络搜索似乎没有发现任何有用的东西。
Python 2.6 添加了string.Formatter,它允许处理和自定义格式样式的字符串,但我没有找到类似的 printf 样式格式字符串的工具。
我正在寻找它来执行诸如验证翻译之类的事情,并可能将 printf 样式的格式字符串转换为格式样式的字符串(甚至是 f 字符串)。
解决方案
在查看文档后,不难与 pyparsing 一起拍打:
import pyparsing as pp
# from https://docs.python.org/3/library/stdtypes.html?highlight=string%20interpolation#printf-style-string-formatting
PCT,LPAREN,RPAREN,DOT = map(pp.Literal, '%().')
conversion_flag_expr = pp.oneOf(list("#0- +"))
conversion_type_expr = pp.oneOf(list("diouxXeEfFgGcrsa%"))
length_mod_expr = pp.oneOf(list("hlL"))
interp_expr = (PCT
+ pp.Optional(LPAREN + pp.Word(pp.printables, excludeChars=")")("mapping_key") + RPAREN)
+ pp.Optional(conversion_flag_expr("conversion_flag"))
+ pp.Optional(('*' | pp.pyparsing_common.integer)("min_width"))
+ pp.Optional(DOT + pp.pyparsing_common.integer("max_width"))
+ pp.Optional(length_mod_expr("length_modifier"))
+ conversion_type_expr("conversion_type")
)
tests = """
Now is the winter of our %s made %(adjective)s %(season)s by this %(relative)s of %(city)s
%(name)s, %(name)s, %(name)s, a %4.8d deaths were not enough for %(name)s
""".splitlines()
for t in tests:
print(t)
for t,s,e in interp_expr.scanString(t):
print("start: {} end: {}\n{}".format(s, e, t.dump()))
print()
印刷:
Now is the winter of our %s made %(adjective)s %(season)s by this %(relative)s of %(city)s
start: 29 end: 31
['%', 's']
- conversion_type: 's'
start: 37 end: 50
['%', '(', 'adjective', ')', 's']
- conversion_type: 's'
- mapping_key: 'adjective'
start: 51 end: 61
['%', '(', 'season', ')', 's']
- conversion_type: 's'
- mapping_key: 'season'
start: 70 end: 82
['%', '(', 'relative', ')', 's']
- conversion_type: 's'
- mapping_key: 'relative'
start: 86 end: 94
['%', '(', 'city', ')', 's']
- conversion_type: 's'
- mapping_key: 'city'
%(name)s, %(name)s, %(name)s, a %4.8d deaths were not enough for %(name)s
start: 4 end: 12
['%', '(', 'name', ')', 's']
- conversion_type: 's'
- mapping_key: 'name'
start: 14 end: 22
['%', '(', 'name', ')', 's']
- conversion_type: 's'
- mapping_key: 'name'
start: 24 end: 32
['%', '(', 'name', ')', 's']
- conversion_type: 's'
- mapping_key: 'name'
start: 36 end: 41
['%', 4, '.', 8, 'd']
- conversion_type: 'd'
- max_width: 8
- min_width: 4
start: 68 end: 76
['%', '(', 'name', ')', 's']
- conversion_type: 's'
- mapping_key: 'name'
如果您更喜欢正则表达式,那么将这个原型转换为可行的东西应该不难。
推荐阅读
- node.js - onRadiusChanged 时无法设置状态
- macos - 我安装了 Perl5.28 并安装了 Net::LibIDN 但 amavisd 找不到它
- c# - 如何将 90 天添加到到期日期或从系统日期减去 90 天
- php - 完整性约束违规:1052 列 'prof_id' 在 where 子句中不明确 Laravel
- r - 我的 AdaBoost 实施有什么问题?
- python - seaborn 热图的自定义刻度
- ruby-on-rails - Rails 容器无法使用 gitlab ci 连接到 mysql 容器
- python - 如何让我的 Python 脚本转到 URL,下载最新文件
- javascript - JS:在复杂的父子数组中按字段查找对象
- c++ - 如何读取输入的几行由空格分隔的整数(在 C++ 中)?