Алекс упомянул pyparsing, поэтому вот подход pyparsing к той же проблеме:
from pyparsing import Word, Suppress, Regex, oneOf, SkipTo
import datetime
DASHES = Word('-').suppress()
LPAR,RPAR,AT = map(Suppress,"()@")
date = Regex(r'\d{2}/\d{2}/\d{4}')
time = Regex(r'\d{2}:\d{2}:\d{2}')
status = oneOf("Busy Available Idle Offline Unavailable")
statechange1 = 'changed status from' + status('fromstate') + 'to' + status('tostate')
statechange2 = 'became' + status('tostate')
linefmt = (DASHES + SkipTo('(')('name') + LPAR + SkipTo(RPAR)('email') + RPAR +
(statechange1 | statechange2) +
AT + date('date') + time('time') + DASHES)
def convertFields(tokens):
if 'fromstate' not in tokens:
tokens['fromstate'] = 'NULL'
tokens['name'] = tokens.name.strip()
tokens['email'] = tokens.email.strip()
d,mon,yr = map(int, tokens.date.split('/'))
h,m,s = map(int, tokens.time.split(':'))
tokens['datetime'] = datetime.datetime(yr, mon, d, h, m, s)
linefmt.setParseAction(convertFields)
for line in text.splitlines():
fields = linefmt.parseString(line)
print "%(name)s/%(email)s %(fromstate)-10.10s %(tostate)-10.10s %(datetime)s" % fields
print:
Mark Grey/mark.grey@gmail.com Busy Available 2010-07-14 16:32:36
Silvia Pablo/spablo@gmail.com NULL Available 2010-07-14 16:32:39
pyparsing позволяет вам присоединять имена к полям результатов (простокак и названные группы в RE-стилизованном ответе Тома Пицкера), плюс действия разбора времени для действия или манипулирования проанализированными действиями - обратите внимание на преобразование отдельных полей даты и времени в истинный объект даты и времени, уже преобразованный и готовый к обработке послеРазбор без дополнительной суеты и суеты.
Вот модифицированный цикл, который просто выводит проанализированные токены и именованные поля для каждой строки:
for line in text.splitlines():
fields = linefmt.parseString(line)
print fields.dump()
печатает:
['Mark Grey ', 'mark.grey@gmail.com', 'changed status from', 'Busy', 'to', 'Available', '14/07/2010', '16:32:36']
- date: 14/07/2010
- datetime: 2010-07-14 16:32:36
- email: mark.grey@gmail.com
- fromstate: Busy
- name: Mark Grey
- time: 16:32:36
- tostate: Available
['Silvia Pablo ', 'spablo@gmail.com', 'became', 'Available', '14/07/2010', '16:32:39']
- date: 14/07/2010
- datetime: 2010-07-14 16:32:39
- email: spablo@gmail.com
- fromstate: NULL
- name: Silvia Pablo
- time: 16:32:39
- tostate: Available
Я подозреваю, что какВы продолжаете работать над этой проблемой, вы найдете другие варианты формата входного текста, определяющего, как изменилось состояние пользователя.В этом случае вы просто добавили бы другое определение, например statechange1
или statechange2
, и вставили его в linefmt
с другими.Я чувствую, что структурирование pyparsing определения парсера помогает разработчикам вернуться к парсеру после того, как что-то изменилось, и легко расширяет свою программу синтаксического анализа.