Вот мой предварительный ответ, не то чтобы я им горжусь. Я взял часть этого из https://stackoverflow.com/a/5824309/131187.
>>> import pyparsing as pp
>>> pp.ParserElement.setDefaultWhitespaceChars(" \t")
>>> EOL = pp.LineEnd().suppress()
>>> keyword = pp.Or([pp.Keyword('Projects'), pp.Keyword('Education')])
>>> line = pp.LineStart() + pp.NotAny(keyword) + pp.SkipTo(pp.LineEnd(), failOn=pp.LineStart()+pp.LineEnd()) + EOL
>>> lines = pp.OneOrMore(line)
>>> section = pp.Or([pp.Keyword('Projects'), pp.Keyword('Education')])('section') + EOL + lines('lines')
>>> sections = pp.OneOrMore(section)
>>> r = sections.parseString(input_text)
Как вы можете видеть чуть ниже этого предложения, синтаксический анализатор успешно собирает информацию и собирает ее таким образом, чтобы ее можно было собрать, как будет показано ниже. Однако я не могу найти способ получить доступ ко всем результатам parseString
, которые так явно доступны.
Я прибегнул к применению eval
к его представлению repr
. Сделав это, я смог выбрать все части и назначить их объекту, похожему на словарь.
Честно говоря, это было бы проще сделать без pyparsing. Прочитайте строку, обратите внимание, является ли это ключевым словом. Если это так, запомните это. Затем, пока вы не прочитаете другое ключевое слово, просто поместите все строки, которые вы прочитали в словаре, под самым последним ключевым словом.
>>> repr(r)
"(['Projects', 'project 1', 'project 2', 'project 3', '', 'Education', 'institution 1', 'institution 2', 'institution 3', 'institution 4', '', 'Projects', 'assignment 5', 'assignment 8', 'assignment 10', ''], {'lines': [(['project 1', 'project 2', 'project 3', ''], {}), (['institution 1', 'institution 2', 'institution 3', 'institution 4', ''], {}), (['assignment 5', 'assignment 8', 'assignment 10', ''], {})], 'section': ['Projects', 'Education', 'Projects']})"
>>> evil_r = eval(repr(r))
>>> evil_r
(['Projects', 'project 1', 'project 2', 'project 3', '', 'Education', 'institution 1', 'institution 2', 'institution 3', 'institution 4', '', 'Projects', 'assignment 5', 'assignment 8', 'assignment 10', ''], {'lines': [(['project 1', 'project 2', 'project 3', ''], {}), (['institution 1', 'institution 2', 'institution 3', 'institution 4', ''], {}), (['assignment 5', 'assignment 8', 'assignment 10', ''], {})], 'section': ['Projects', 'Education', 'Projects']})
>>> evil_r[1]['lines']
[(['project 1', 'project 2', 'project 3', ''], {}), (['institution 1', 'institution 2', 'institution 3', 'institution 4', ''], {}), (['assignment 5', 'assignment 8', 'assignment 10', ''], {})]
>>> evil_r[1]['section']
['Projects', 'Education', 'Projects']
>>> from collections import defaultdict
>>> section_info = defaultdict(list)
>>> for k, kind in enumerate(evil_r[1]['section']):
... section_info[kind].extend(evil_r[1]['lines'][k][0][:-1])
>>> for section in section_info:
... section, section_info[section]
...
('Education', ['institution 1', 'institution 2', 'institution 3', 'institution 4'])
('Projects', ['project 1', 'project 2', 'project 3', 'assignment 5', 'assignment 8', 'assignment 10'])
EDIT: Или вы можете сделать это. Требует уборки. По крайней мере, он не использует ничего необычного.
>>> input_text = open('temp.txt').read()
>>> import pyparsing as pp
>>> pp.ParserElement.setDefaultWhitespaceChars(" \t")
>>> from collections import defaultdict
>>> class Accum:
... def __init__(self):
... self.current_section = None
... self.result = defaultdict(list)
... def __call__(self, s):
... if s[0] in ['Projects', 'Education']:
... self.current_section = s[0]
... else:
... self.result[self.current_section].extend(s[:-1])
...
>>> accum = Accum()
>>> EOL = pp.LineEnd().suppress()
>>> keyword = pp.Or([pp.Keyword('Projects'), pp.Keyword('Education')])
>>> line = pp.LineStart() + pp.NotAny(keyword) + pp.SkipTo(pp.LineEnd(), failOn=pp.LineStart()+pp.LineEnd()) + EOL
>>> lines = pp.OneOrMore(line)
>>> section = pp.Or([pp.Keyword('Projects'), pp.Keyword('Education')]).setParseAction(accum) + EOL + lines.setParseAction(accum)
>>> sections = pp.OneOrMore(section)
>>> r = sections.parseString(input_text)
>>> accum.result['Education']
['institution 1', 'institution 2', 'institution 3', 'institution 4']
>>> accum.result['Projects']
['project 1', 'project 2', 'project 3', 'assignment 5', 'assignment 8', 'assignment 10']
person
Bill Bell
schedule
17.08.2017
setResultsName
в разделах project_section и education_section добавляйтеlistAllMatches=True
. Тогда я думаю, что ваш код будет работать как есть. - person PaulMcG   schedule 18.08.2017listAllMatches=True
группирует результаты вместе, спасибо! - person scottwernervt   schedule 18.08.2017