2016-02-01 2 views
1

Я пытаюсь извлечь идентификатор и данные из следующей строки примера. Я определил id как что-то, что будет иметь алфавиты и несколько других символов, но исключая запятую. Я ожидал, что пиперация не будет забирать цифру 1 данных как часть идентификатора, потому что данные являются смежным блоком, который включает запятую и запятую, исключен из идентификатора. Должно ли pyparsing не отклонять часть данных в целом как id, потому что этот непрерывный блок данных содержит другие символы, не определенные в id? Мои ожидания, что правила применяются к словам в целом и не кусками словpyparsing определение слова как непрерывный блок символов

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' ], { 'данные': [('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, а также использовать 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) - это действительно очень распространенная ошибка для Pyparsing разработчиков.)

Я также вижу, что вы используете имена результатов - это хорошая привычка , Поскольку у вас их есть, я предлагаю вам использовать 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 
+0

Параметр 'stopOn' ключевое слово аргумент будет включен в следующий выпуск Pyparsing, версия 2.1.0. – PaulMcG