Определение слова как смежного блока символов

Я пытаюсь извлечь идентификатор и данные из следующей строки образца. Я определил идентификатор как что-то, что будет иметь алфавиты и несколько других символов, кроме запятой. Я ожидал, что 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
Другие вопросы по тегам