正则表达式为45个十六进制数或48个十六进制数的模式 - Python

时间:2012-09-25 13:10:51

标签: python regex

我的文件包含45个十六进制数字,用空格分隔或48个十六进制数字,用空格分隔。我个人而不是整体需要所有这些数字。我目前正在使用蛮力方法获得45个数字。

pattern = re.compile("([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s([0-9a-f]{2})\s")

然而,即便如此,我仍然无法弄清楚如何在48十六进制数字实例中提取剩余的三个数字。你能帮我解决这个问题吗?

我会避免使用下面的解决方案(如果有效则没有尝试),因为我将不得不为每个实例拆分字符串,即考虑它提供正确的输出!

(((?:[0-9a-f]{2})\s){48})|(((?:[0-9a-f]{2})\s){45})

谢谢!

6 个答案:

答案 0 :(得分:7)

编写长RE时,请考虑使用re.VERBOSE使其更具可读性。

pattern = re.compile(r"""
 ^( [0-9a-fA-F]{2} (?: \s [0-9a-fA-F]{2} ){44}
                (?:(?: \s [0-9a-fA-F]{2} ){3} )? )$ 
""", re.VERBOSE)

读为:两个十六进制数字,后跟44次(空格后跟两个十六进制数字),可选后跟3次(空格后跟两个十六进制数字)。

测试:

>>> pattern.match(" ".join(["0f"] * 44))
>>> pattern.match(" ".join(["0f"] * 45))
<_sre.SRE_Match object at 0x7fd8f27e0738>
>>> pattern.match(" ".join(["0f"] * 46))
>>> pattern.match(" ".join(["0f"] * 47))
>>> pattern.match(" ".join(["0f"] * 48))
<_sre.SRE_Match object at 0x7fd8f27e0990>
>>> pattern.match(" ".join(["0f"] * 49))

最后,要检索各个数字,请对匹配结果.group(0).split()进行检索。这比编写将所有数字分成不同组的RE要容易得多。

编辑:好的,这是如何解决原始问题。只需动态构建RE。

chunk = r"""([0-9a-fA-F]{2}\s)"""
pattern = re.compile(chunk * 45 + "(?:" + chunk * 3 + ")?")

答案 1 :(得分:5)

仅仅使用两种模式会不会更容易?这样你就不需要复杂的逻辑来处理子组了。

pattern1 = re.compile("([0-9a-f]{2}\s){45}")
pattern2 = re.compile("([0-9a-f]{2}\s){48}")

答案 2 :(得分:4)

我相信您可能正在寻找的是re.findall

取决于该字符串的其余部分的外观......这对我来说是一个每个十六进制的字符串列表

import re
reg = re.compile("[0-9a-f]{2}\s")
hexes = "ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12 ab 12"
hexList = re.findall(reg, hexes)

这会让你获得所有2个字符串的列表。从那里将它分成45/48是微不足道的,这取决于你从中获取的字符串中的其他类型的数据。

但是,如果您在字符串中有大量数据,则无法使用。

或者,虽然你说你不想这样做,但做这样的事情确实非常简单:

reg = re.compile("([0-9a-f]{2}\s){45,48}") #Edit: Missed an open paren
match = reg.search(hexes)
if match:
    splitList = match.group().split()

然后你有一份所有数字的清单,很好地分开了。

答案 3 :(得分:1)

我喜欢您的硬连接方法(根据您的特定需求),但我会通过乘法生成模式字符串。我的例子预计3个组和5个组(只是为了使测试更容易):

pattern = re.compile(r'(?:' +
  r'\s+'.join([ r'([a-f0-9]{2})' ] * 5) +
  r')|(?:' +
  r'\s+'.join([ r'([a-f0-9]{2})' ] * 3) +
  r')')
m1 = pattern.match('ab cd ef')
m2 = pattern.match('ab cd ef 34 56')

m.groups()的结果类似于(None, None, None, None, None, 'ab', 'cd', 'ef'),对于3个组,类似于('ab', 'cd', 'ef', '34', '56', None, None, None),对于5个组。因此,您可以检查m.groups()[0]是否为无找到你得到的版本(45或48),然后使用groups()[:48]或groups()[48:]。

确保在较小的数字(45)之前有较大的数字(48)。

此模式当然可以与findallsearchfinditer或类似模式一起使用,如果您有办法知道一个十六进制组的结束位置和下一个十六进制组开始的位置。在这个例子中,hexnumbers之间的空格必须是空格或制表符,其他东西(如换行符)将hexenumber组彼此分开:

pattern = re.compile(r'(?:' +
  r'[ \t]+'.join([ r'([a-f0-9]{2})' ] * 5) +  # replaced \s by [ \t]
  r')|(?:' +
  r'[ \t]+'.join([ r'([a-f0-9]{2})' ] * 3) +
  r')')
print [ i.groups() for i in pattern.finditer(
    'ab cd ef 34 56\nab cd ef 34 56\nab cd ef\nab cd ef\n') ]

[ ('ab', 'cd', 'ef', '34', '56', None, None, None),
  ('ab', 'cd', 'ef', '34', '56', None, None, None),
  (None, None, None, None, None, 'ab', 'cd', 'ef'),
  (None, None, None, None, None, 'ab', 'cd', 'ef') ]

答案 4 :(得分:0)

您能考虑使用re.findall吗?

>>> import re
>>> pat = r'([0-9A-Fa-f]+)'
>>> s= '45f 567B 45C67'
>>> for i in re.findall(pat, s):
    print i


45
567B
45C67

使用此方法,无论您的文件中有多少个数字。

答案 5 :(得分:0)

如果您知道该文件包含十六进制数据,只需将整个文件读入一个字符串,然后将其拆分为空格。这适用于45,48或任何其他数字。

import re
splitter = re.compile('\s+')
data = splitter.split(file(filename,'r').read())