Python: шестнадцатеричное регулярное выражение вопрос - PullRequest
2 голосов
/ 03 августа 2010

Я хочу проанализировать вывод программы последовательного мониторинга под названием Docklight (я очень рекомендую это) Он выводит шестнадцатеричные строки: или последовательность (две заглавные шестнадцатеричные цифры, за которыми следует пробел). соответствующее регулярное выражение: ([0-9A-F]{2} )+ например: '05 03 DA 4B 3F '

Когда программа обнаруживает определенные последовательности символов, она помещает комментарии в шестнадцатеричную строку. например:

'05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'

комментарии - строки следующего формата ' .+ ' (последовательность символов, перед которыми стоит пробел, а затем пробел)

Я хочу избавиться от комментариев. например, шестнадцатеричная строка выше отфильтрованной будет:

'05 03 04 01 0A 03 08 0B BD AF 0D 0A '

как мне сделать это с помощью регулярного выражения?

Ответы [ 6 ]

4 голосов
/ 03 августа 2010

Вы можете попробовать re.findall():

>>> a='05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
>>> re.findall(r"\b[0-9A-F]{2}\b", a)
['05', '03', '04', '01', '0A', '03', '08', '0B', 'BD', 'AF', '0D', '0A']

В регулярном выражении \b соответствует "границе слова".

Конечно, ваш ввод будет неоднозначным, если на последовательный монитор вставляется что-то вроде THIS BE THE HEADER.

0 голосов
/ 03 августа 2010

Как насчет решения, которое на самом деле использует отрицание регулярных выражений? ;)

result = re.sub(r"[ ]+(?:(?!\b[0-9A-F]{2}\b).)+", "", subject)
0 голосов
/ 03 августа 2010

Почему регулярное выражение?Более питоническим для меня является (исправлено для шестнадцатеричной, а не обычной цифры):

command='05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
print ' '.join(com for com in command.split()
               if len(com)==2 and all(c.upper() in '0123456789ABCDEF' for c in com))
0 голосов
/ 03 августа 2010

Несмотря на то, что вы уже получили два ответа, которые нашли все шестнадцатеричные числа, здесь то же самое с прямым регулярным выражением, которое находит весь текст, не похожий на шестнадцатеричное число (при условии, что это две буквы / цифры в верхнем / нижнем регистре 0-9 и диапазон АФ, за которым следует пробел).

Как-то так (извините, я не питонер, но вы поняли):

newstring = re.sub(r"[^ ]+(?<![0-9A-Fa-f ]{2}|^.)", "", yourstring)

Работает "оглядываясь назад ".Он находит каждую последовательную непробельную подстроку, а затем оглядывается назад с (?<!....).Там написано: «если два предыдущих символа не были шестнадцатеричным числом, то получилось».Маленький ^. в конце предотвращает неправильное совпадение с первым символом строки.

Edit

Как и предположил Алан Мур, вот та же идея с положительным прогнозным выражением:

newstring = re.sub(r"(?>\b[0-9A-Fa-f ]{2}\b)", "", yourstring)
0 голосов
/ 03 августа 2010

Использование вашего регулярного выражения

hexa = '([0-9A-F]{2} )+'
" ".join(re.findall(hexa, line))
0 голосов
/ 03 августа 2010

Может быть проще найти все шестнадцатеричные числа, предполагая, что вставленные строки не будут содержать совпадения:

>>> data = '05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
>>> import re
>>> pattern = re.compile("[0-9A-F]{2} ")
>>> "".join(pattern.findall(data))
'05 03 04 01 0A 03 08 0B BD AF AD 0D 0A '

В противном случае вы можете использовать тот факт, что вставленным строкам предшествует два пробела:

>>> data = '05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
>>> re.sub("(  .*?)(?=( [0-9A-F]{2} |$))","",data)
'05 03 04 01 0A 03 08 0B BD AF 0D 0A'

При этом используется предварительный просмотр для определения окончания вставленной строки.Он ищет либо шестнадцатеричную строку, окруженную пробелами, либо конец исходной строки.

...