解析器,用于printf样式的格式字符串

时间:2018-07-11 08:34:00

标签: python parsing format printf std

是否有一种很好的方法来解析printf样式的格式字符串并获取各种位(带有可处理选项的文字文本和格式点)作为标准库的一部分,还是不能作为第三方库呢?我在stdlib中找不到一个,而且网络搜索似乎没有发现任何有用的信息。

Python 2.6添加了string.Formatter,它允许处理和自定义格式样式字符串,但是我没有找到类似的工具来处理printf样式格式字符串。

我正在寻找它来执行诸如验证翻译之类的工作,并可能将printf样式的格式字符串转换为格式样式的字符串(甚至f字符串)。

1 个答案:

答案 0 :(得分:1)

在查看文档后,不难将它们与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'

如果您喜欢使用正则表达式,则不难将其原型转换为可行的东西。