ネットワークの勉強を兼ねてパケットキャプチャを自作中です。
その中でEthernetフレームをパースする処理を書いていたのですが、
ソケットで受信した生データを文字列におこすと、MACアドレスは
セミコロン":"が挿入されていない状態で取得されます。
セミコロンを挿入したい
000c29ecc97a
↓こうしたい↓
00:0c:29:ec:c9:7a
文字列リストなんだから、2文字ずつのサブリストに分割して":"でjoinすればいいか。
と思ってググってみるとn文字のサブリストに分割するテクニックとしてzip(*[iter(s)]*n)を発見。
分割、結合でセミコロンを挿入
>>> s = '000c29ecc97a'
>>> zip(*[iter(s)]*2)
>>> [('0', '0'), ('0', 'c'), ('2', '9'), ('e', 'c'), ('c', '9'), ('7', 'a')]
# ":"で連結!
>>> ':'.join(map(''.join, zip(*[iter(s)]*2)))
'00:0c:29:ec:c9:7a'
':'.join(map(''.join, zip(*[iter(s)]*2)))
がよみにくいっ。
テクニックとしてはいいのですが、知らないとわかりづらいので気持ち悪いです。
次に思いついたのが正規表現で置換する方法。
正規表現でセミコロンを挿入
>>> import re
>>> s = '000c29ecc97a'
>>> raw_mac_ptn = r'([0-9A-F]{2})(?!$)'
>>> mac_addr = re.sub(raw_mac_ptn, r'\1:', s)
>>> mac_addr
'00:0c:29:ec:c9:7a'
こっちのほうが見やすいかな。末尾に":"が挿入されないよう否定先読み(?!$)が肝です。