Определение слова как смежного блока символов
Я пытаюсь извлечь идентификатор и данные из следующей строки образца. Я определил идентификатор как что-то, что будет иметь алфавиты и несколько других символов, кроме запятой. Я ожидал, что pyparsing не получит цифру 1 данных как часть идентификатора, потому что данные являются непрерывным блоком, который включает запятую и запятая исключена из идентификатора. Должен ли pyparsing не отклонять часть данных в целом как id, потому что этот непрерывный блок данных содержит другие символы, не определенные в части id? Я ожидал, что правила применяются к словам в целом, а не к словам
joinTokensViaSpace = lambda tokens: " ".join(" ".join(t.split()) for t in tokens)
parser= OneOrMore(Word(alphanums+'-/.'))('id').setParseAction(joinTokensViaSpace) + Word(nums+',.()')('data')
parser.parseString(' XXX Y/123 1,234.567890')
вывод я получаю
(['XXX Y/1231', ',234.567890'], {'data': [(',234.567890', 1)], 'id': [('XXX Y/1231', 0)]})
вывод, который я ожидаю (['XXX Y/123', '1,234.567890'], {'data': [('1,234.567890', 1)], 'id': [('XXX Y/123', 0)]})
1 ответ
В общем Word
обычно анализирует пробелы, но это не гарантируется, как вы нашли. Я попытался немного изменить свой парсер, чтобы добавить Word
необязательно asKeyword=True
аргумент, а также с помощью Regex
с окружающими \b
маркеры, но в обоих случаях, ',' в 1,234.567890
удовлетворены нормальным поведением разрыва слова.
Самое простое решение состоит в том, чтобы вставить отрицательный взгляд внутрь вашего OneOrMore
до сопоставления на Word(alphanums+'-/.')
:
number = Word(nums+',.()')
parser= OneOrMore(~number + Word(alphanums+'-/.'))('id')\
.setParseAction(joinTokensViaSpace) + number('data')
Таким образом, прежде чем начать другой Word
парсер сначала проверяет, есть ли у него потенциал number
и только продолжается, если это не так. С этим изменением проанализированный вывод будет таким, как вы ожидаете. (Возможно, я должен добавить stopOn
аргумент OneOrMore
а также ZeroOrMore
, лайк OneOrMore(Word(alphanums+'-/.'), stopOn=number)
- это действительно очень распространенная ошибка для разработчиков приложений.)
Я также вижу, что вы используете имена результатов - это хорошая привычка. Так как у вас есть, я предлагаю вам использовать dump()
как лучший инструмент для изучения ParseResults
структура возвращается parseString
,
result = parser.parseString(' XXX Y/123 1,234.567890')
print result.dump()
печать
['XXX Y/123', '1,234.567890']
- data: 1,234.567890
- id: XXX Y/123