Pyparsing: пробел как допустимый токен

Я использую pyparser для обработки вывода преобразователя шестнадцатеричного текста в текст. Он выводит по 16 символов в строке, разделенных пробелами. Если шестнадцатеричное значение является печатным символом ASCII, этот символ печатается, в противном случае преобразователь выводит точку (.)

В основном вывод выглядит так:

. a . v a l i d . s t r i n g .
. a n o t h e r . s t r i n g .
. e t c . . . . . . . . . . . .

Мой код pyparsing для описания этой строки:

dump_line = 16 * Word(printables, exact=1)

Это работает нормально, пока преобразователь шестнадцатеричного значения в текст не достигнет шестнадцатеричного значения 0x20, что приведет к выводу пробела.

l i n e . w . a .   s p a c e .

В этом случае pyparsing игнорирует выводимое пространство и берет символы из следующей строки, чтобы сделать «квоту» в 16 символов.

Может кто-нибудь предложить, как я могу сказать pyparsing ожидать 16 символов, каждый из которых разделен пробелом, где пробел также может быть допустимым символом?

Заранее спасибо. Дж


person JS.    schedule 04.01.2011    source источник


Ответы (2)


Так как это имеет значительные пробелы, вам нужно указать своему символьному выражению оставить начальные пробелы в покое. Посмотрите, как это делается ниже в определении дампа:

hexdump = """\
. a . v a l i d . s t r i n g . 
. a n o t h e r . s t r i n g . 
. e t c . . . . . . . . . . . . 
l i n e . w . a .   s p a c e . 
. e t c . . . . . . . . . . . . 
"""

from pyparsing import oneOf, printables, delimitedList, White, LineEnd

# expression for a single char or space
dumpchar = oneOf(list(printables)+[' ']).leaveWhitespace()

# convert '.'s to something else, if you like; in this example, '_'
dumpchar.setParseAction(lambda t:'_' if t[0]=='.' else None)

# expression for a whole line of dump chars - intervening spaces will
# be discarded by delimitedList
dumpline = delimitedList(dumpchar, delim=White(' ',exact=1)) + LineEnd().suppress()

# if you want the intervening spaces, use this form instead
#dumpline = delimitedList(dumpchar, delim=White(' ',exact=1), combine=True) + LineEnd().suppress()

# read dumped lines from hexdump
for t in dumpline.searchString(hexdump):
    print ''.join(t)

Отпечатки:

_a_valid_string_
_another_string_
_etc____________
line_w_a_ space_
_etc____________
person PaulMcG    schedule 04.01.2011
comment
Привет, Пол. Спасибо за быстрый ответ. Я получаю pyparsing.ParseException: ожидаемый конец строки, если я не удалю LineEnd(). Распознает ли LineEnd() перевод строки Linux (только 0x0A) как конец строки? - person JS.; 05.01.2011
comment
Вы используете этот код, как опубликовано, вы анализируете каждую строку отдельно? LineEnd() должен искать \n, и я предполагаю, что Python сделает правильную вещь, зависящую от ОС, для вашей системы. Я только что сделал грубый тест в интерпретаторе как на Windows, так и на Linux: LineEnd() == '\n' и оба вернули True. - person PaulMcG; 05.01.2011
comment
Спасибо, Пол! Это решение прекрасно работает. Проблема LineEnd() оказалась результатом моего использования parseString() вместо цикла FOR, вызывающего searchString(). Теперь это работает. Еще раз спасибо за помощь и быстрые ответы! - person JS.; 05.01.2011

Рассмотрите возможность использования другого способа удаления пробелов

>>> s=". a . v a l i d . s t r i n g ."
>>> s=s[::2]
>>> s
'.a.valid.string.'
person John La Rooy    schedule 04.01.2011
comment
Да, pyparsing кажется излишним для этого. - person kindall; 05.01.2011
comment
Указанная проблема представляет собой небольшую часть гораздо большего отчета, для разбора которого требуется сила pyparsing. В противном случае, да, это было бы гораздо более прямое решение. - person JS.; 05.01.2011
comment
Не могли бы вы разумно заставить PyParsing рассматривать весь дамп ASCII как один токен, а затем применять это преобразование ко всему дампу? - person kindall; 05.01.2011
comment
Да, если бы весь отчет был в таком формате. Дамп ASCII представляет собой лишь один небольшой раздел гораздо большего отчета с множеством различных текстовых полей, форматов и макетов. Если бы весь отчет был в формате, который я описываю в задаче, это было бы гораздо более кратким решением, и pyparsing был бы излишним. - person JS.; 05.01.2011
comment
Четко ли разграничено рассматриваемое поле? Если да, то позволяет ли pyparsing преобразовывать текст этого поля по мере его обработки с помощью лямбда-выражения, применяющего идею среза этого ответа? - person codeshot; 22.03.2015