4

私のファイルには、空白で区切られた 45 の 16 進数、または空白で区切られた 48 の 16 進数が含まれています。全体としてではなく、これらすべての数値が個別に必要です。私は現在、ブルート フォース メソッドを使用して 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 の 16 進数のインスタンスで残りの 3 つの数字を抽出する方法がわかりません。この問題を単純化する方法を教えてください。

後でインスタンスごとに文字列を分割する必要があるため、以下のような解決策は避けます (うまくいくかどうか試していません)。つまり、適切な出力が得られると考えてください!

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

ありがとうございました!

4

6 に答える 6

7

長い正規表現を記述するときは、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)

読み方: 2 つの 16 進数の後に 44 回 (スペースの後に 2 つの 16 進数が続く)、オプションで 3 回続く (スペースの後に 2 つの 16 進数が続く)。

テスト:

>>> 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 + ")?")
于 2012-09-25T13:31:19.067 に答える
5

2 つのパターンを使用する方が簡単ではないでしょうか。そうすれば、サブグループを処理するための複雑なロジックは必要ありません。

pattern1 = re.compile("([0-9a-f]{2}\s){45}")
pattern2 = re.compile("([0-9a-f]{2}\s){48}")
于 2012-09-25T13:21:24.180 に答える
4

あなたが探しているのはre.findallだと思います

その文字列の残りの部分がどのように見えるかに応じて..これは、各16進数の文字列のリストを取得するのに役立ちました

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 文字の 16 進数すべてのリストが取得されます。そこから、取得している文字列に含まれる他の種類のデータに応じて、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()

そして、うまく分割されたすべての数字のリストがあります。

于 2012-09-25T13:40:31.237 に答える
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')

の結果は、3 のグループの場合と 5 のグループの場合のようm.groups()になります。したがって、取得したバージョン (45 または 48) を見つけるために None かどうかを確認してから、groups()[:48] またはいずれかを使用できます。グループ()[48:]。(None, None, None, None, None, 'ab', 'cd', 'ef')('ab', 'cd', 'ef', '34', '56', None, None, None)m.groups()[0]

小さい数字 (45) の前に大きい数字 (48) があることを確認してください。

このパターンは、1 つの 16 進数グループがどこで終了し、次のグループが開始するかを知る方法がある場合は、もちろんfindallsearch、 、 などで使用できます。finditerこの例では、16 進数間の空白はスペースまたはタブである必要があり、他のもの (改行など) は 16 進数グループを互いに分離します。

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') ]

→</p>

[ ('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') ]
于 2012-09-25T14:10:22.677 に答える
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

この方法では、ファイルに含まれる数字の数に関係ありません。

于 2012-09-25T13:17:12.213 に答える
0

ファイルに16進データが含まれていることがわかっている場合は、ファイル全体を文字列に読み取ってから、空白で分割します。これは、45、48、またはその他の数字で機能します。

import re
splitter = re.compile('\s+')
data = splitter.split(file(filename,'r').read())
于 2012-09-25T13:31:08.993 に答える