#python #regex
#python #регулярное выражение
Вопрос:
Сопоставьте шаблон, содержащий неопределенное количество 2-значных шестнадцатеричных чисел, разделенных одним пробелом.
0000000: 4B 0B 69 00 04 00 00 00 EE 03 00 00 00 00 00 00 abcdefg
==> 4B 0B 69 00 04 00 00 00 EE 03 00 00 00 00 00 00
12345 4B 0B 69 00 04 00 00 00 EE 03 00 00 01 02
==> 4B 0B 69 00 04 00 00 00 EE 03 00 00
# (because there are more than one space between 00 and 01)
12: 4B 0B 69 00 04 00 00 00 EE 2
==> 4B 0B 69 00 04 00 00 00 EE
5 4B 0B 69 00 04 00 3
==> 4B 0B 69 00 04 00
ZZ 4B 0B 69 00 04 00 DD MN
==> 4B 0B 69 00 04 00 DD
# Because ZZ and MN are not hex numbers
Ответ №1:
Поиск сзади должен решить эту проблему. Вы ищете- b(?<! {2})([da-f]{2})(?= {1})
(с нечувствительным флагом)
Вот демо
Объяснение
b(?<! {2})([da-f]{2})(?= {1})
b
— соответствует границе слова, это в основном просто для того, чтобы убедиться, что он не соответствует таким вещам, как 45 из 12345 в12345 4B 0B 69 00 04 00 00 00 EE 03 00 00 01 02
(?<! {2})
— это гарантирует, что совпадение не имеет 2 пробела слева([da-f]{2})
— фиксирует шестнадцатеричные числа из 2 цифр(?= {1})
— После этого проверяется наличие единственного пробела
Код
В Python вы можете использовать флаг re.findall
with re.I
для поиска всех шестнадцатеричных чисел в заданной строке.
import re
match = re.findall(r'b(?<! {2})([da-f]{2})(?= {1})', '0000000: 4B 0B 69 00 04 00 00 00 EE 03 00 00 00 00 00 00 abcdefg', flags=re.I)
print(match)
Вывод
['4B',
'0B',
'69',
'00',
'04',
'00',
'00',
'00',
'EE',
'03',
'00',
'00',
'00',
'00',
'00',
'00']
Ответ №2:
Мои 2 цента: (?:^|s)([0-9a-fA-F]{2}(?:s|$))
https://regex101.com/r/I0gQlU/2
(?:^|s)
: либо начало строки, либо пробел[0-9a-fA-F]{2}
: 2 шестнадцатеричных цифры(?:s|$)
: либо заканчивается пробелом, либо заканчивается строкой
Ответ №3:
Вот как вы могли бы сделать это с помощью понимания списка, используя hexdigits
из string
библиотеки. Не уверен, как выполнить с помощью регулярного выражения:
import string
s = 'ZZ 4B 0B 69 00 04 00 DD MN'
s = re.sub(r'ss.*', '', s)
' '.join([i for i in s.split(' ') if len(i) == 2 if i[0:1] in string.hexdigits])
'4B 0B 69 00 04 00 DD'
По сути, он перебирает строку, чтобы проверить, являются ли оба шестнадцатеричными.
Комментарии:
1. Спасибо за ответ, сложность заключается в том, что приведенное выше понимание списка не может обрабатывать такие случаи,
5 4B 0B 69 00 04 00 3
поскольку оно дает результат5 4B 0B 69 00 04 00 3
, но желаемый4B 0B 69 00 04 00
2. @CodingNow смотрите мой обновленный ответ с
if len(i) == 2
Shoot, к сожалению, он также не сохранит00
, поскольку это обманчиво. Я попытаюсь придумать более надежное решение.3. вы не учитываете 1 или более пробелов, эта информация теряется из-за
split()
4. это не улучшит ситуацию, потому что
split()
иsplit(' ')
здесь одинаковы, ваш код завершится ошибкой во втором примере5.
s
иs s
являются «эквивалентными», второеs
не имеет цели, лучше использоватьs{2,}
, илиss
. это сбивает с толку то, что вы хотите