如何使用pyparsing将令牌分组放置在不同的位置?

时间:2013-08-20 08:39:10

标签: python pyparsing

我有一个简单的句子 - " tok0,084040,tok1,tok2,231108 "其中 084040 是时间(08:40:40), 231108 是日期(23.11.2008)

按照pyparsing文档,我已经编写了解析令牌的规则:

    from pyparsing import *
    d = Literal(',').suppress()
    two_digits = Word(nums, exact=2)
    tok0 = Word(nums)
    time_token = two_digits("hour") + two_digits("min") + two_digits("sec")
    tok1 = Word(alphas)
    tok2 = oneOf('A B C')
    date_token = two_digits("day") + two_digits("month") + two_digits("year")
    grammar = (tok0 + d + time_token + d + tok1 + d + tok2 + d + date_token)
我想要的是在我的 ParseResults 中有一个逻辑组,由 time_token date_token 组成,这样我就可以使用 setParseAction , setResultsName 。像
Group(time_token + date_token)
这样的东西,认为它们不相邻。
dreamGroup = Group(time_token + date_token)("datetime").setParseAction(myFn)
parseResults = grammar.parseString("123,084040,ABC,A,231108")
datetime = parseResults.datetime
P.S。:grammar.parseString的结果应该是ParseResults的一个实例。

2 个答案:

答案 0 :(得分:3)

您可以在解析操作的正文中添加结果名称,它们将保留在已解析的标记中。

def addDateTimeResults(tokens):
    tokens['date'] = ('20'+tokens.year, tokens.month, tokens.day)
    tokens['time'] = (tokens.hour, tokens.min, tokens.sec)
    tokens['datetime'] = ParseResults([tokens.date, tokens.time])
    for name in ('date', 'time'):
        tokens['datetime'][name] = tokens[name]
grammar.setParseAction(addDateTimeResults)

现在,在您的示例代码中,添加对dump()的调用以查看您获得的内容:

parseResults = grammar.parseString("123,084040,ABC,A,231108")
datetime = parseResults.datetime
print datetime.dump()

你得到:

[('2008', '11', '23'), ('08', '40', '40')]
- date: ('2008', '11', '23')
- time: ('08', '40', '40')

或者不是插入和返回元组,而是可以构造一个实际的Python日期时间对象,然后返回它:

import datetime
def addDateTimeResults(tokens):
    dtfields = map(int, (tokens[fld] for fld in "year month day hour min sec".split()))
    # adjust 2-digit year for 21st century
    dtfields[0] += 2000
    tokens['datetime'] = datetime.datetime(*dtfields)

现在print parseResults.datetime给出:

2008-11-23 08:40:40

这是Python日期时间对象的默认字符串表示形式。

答案 1 :(得分:1)

更改语法级别的parseResults解决了这个问题。所以我稍微修改了你的答案,它就像一个魅力。


def changeGrammarParseResults(s, loc, toks):
    toks['datetime_8601'] = datetime.datetime(
        toks.pop('year'), toks.pop('month'), toks.pop('day'),
        toks.pop('hour'), toks.pop('minute'), toks.pop('second'),
        tzinfo=pytz.utc).isoformat()