2014-12-23 3 views
0

У меня есть список, который содержит только одну строку с шестнадцатеричными значениями, такими как \ x01, \ x02 ... Эти шестнадцатеричные значения никогда не встречаются в начале и не в конце строка.Извлечь данные из строки, которая находится между шестнадцатеричными значениями

list1 = ["Test String\x01111\x05Test String\x02GG\x01TEXT123"] 

Я хотел бы извлечь все данные в этой строке, которая находится между шестнадцатеричными значениями. Таким образом, данные, которые я хочу извлечь: Test String, 111, Test String, GG, TEXT123. Как я могу это сделать?

Пожалуйста, обратите внимание, что также может быть "пустой данные":

      # between \x01 and \x05 is nothing 
list2 = ["Test String\x01\x05Test String2"] 
         # this should be saved even it is "" 

Выход в данном примере должно быть: Test String, EMPTY STRING (я имею в виду "«), Test String2

ответ

3

Это хороший прецедент для re.split, который ведет себя аналогично str.split, но использует в качестве разделителя регулярное выражение (а не строку).

Когда вы говорите «шестнадцатеричное значение», я полагаю, вы имеете в виду «непечатаемые ASCII символ», то есть в диапазоне 0x00 до 0x1F плюс 0x7F.

>>> import re 
>>> re.split('[\x00-\x1f\x7f]', 'Test String\x01111\x05Test String\x02GG\x01TEXT123') 
['Test String', '111', 'Test String', 'GG', 'TEXT123'] 
>>> re.split('[\x00-\x1f\x7f]', 'Test String\x01\x05Test String2') 
['Test String', '', 'Test String2'] 
+0

спасибо, что отлично. Сначала я попробовал обычную функцию 'split()', но re.split хорош. – JohnB

+0

* + 1 * Хорошее решение. –

1

Вы можете использовать itertools.groupby здесь, чтобы сгруппировать все элементы, попадающие в диапазон печати ASCII, и для предметов в непечатаемом диапазоне, если их длина группы больше 1, а затем возвращается '':

from itertools import groupby 
def solve(s):           
    for k, g in groupby(s, lambda x: 32 <= ord(x) < 127): 
     if k: 
      yield ''.join(g) 
     else: 
      g = list(g) 
      if len(g) > 1: 
       yield '' 
...     
>>> s = "Test String\x01111\x05Test String\x02GG\x01TEXT123" 
>>> list(solve(s))       
['Test String', '111', 'Test String', 'GG', 'TEXT123'] 
>>> s = "Test String\x01\x05Test String2"  
>>> list(solve(s)) 
['Test String', '', 'Test String2'] 
1
>>> import re  
>>> re.findall(r'[\x01-\x05]([^\x01-\x05]*)[\x01-\x05]', list1[0]) 
['111', 'GG'] 

Ваша спецификация для «шестнадцатеричных значений, как \ x01 \ x02 ...» немного неоднозначная - я предполагаю, ради фрагмента коды выше «значений между \ x01 и \ x05 включен »- если вам нужен другой диапазон« шестнадцатеричных значений », который легко настроить, конечно.

Ключевая идея заключается в том, чтобы найти «один hex value, то ноль или более non-hex values, то один hex value», а также получить центральный «ноль или более» часть, заключив его в скобки, тем самым делая его группу в регулярное выражение. Таким образом, findall вернет список всех содержимого групп, который, как представляется, соответствует вашему запросу.

Смежные вопросы