そうか、Perl でビットシフトは10進数に変換してから行うのか・・・[Perl]
(2012-02-16 07:00:11) by shinoda
< ページ移動: 1 2 >
とあるバイナリデータがある。
そのデータは、1バイト(8ビット)を2ビットずつに区切って、全部で60個ある装置の状態をヘルスデータとして流してくる。データの大きさは 2ビット x 60装置 = 15バイト。
その 2ビットの内容は、
0(00)...NG
1(01)...WRN(警告)
2(10)...OK
という具合。(カッコ内は 2進数)
その 1バイトの中で、装置番号の若いものが下位ビットにセットされる。
だから、4台の装置の状態が、
No.1 10(OK)
No.2 01(WRN)
No.3 10(OK)
No.4 00(NG)
となっていれば、'10011000'ではなく、下位から順にセットしていき '00100110' となる。16進であれば、0x26 だ。
この情報を装置の番号順に取っていきたい。つまり、15バイトのデータから1バイトずつ抜き出して、さらにその 1バイトの中の下位ビットから 2ビットずつ取っていきたい。
'00100110' というデータであれば、
1.下位 2ビットだけを残す論理積計算をおこなう。
('00000011' という 2進数と論理積を取れば、下位 2ビットの情報だけを抜き出せる)
2.論理積の計算後、次の処理のため 2ビット下位にシフト。
('00100110'を、2ビット右にシフトして'00001001'に)
この処理を、1バイト分(つまり 4回)繰り返し・・・となる。
$v1 = "\x26\xAA\x26\xAA\x26\xAA\x26\xAA\x26\xAA\x26\xAA\x26\xAA\x00"; # データ 15byte(60装置分)
$v2 = 3; # 00000011
for ($i = 0; $i < 15; $i++) {
# 1byte 抜き出す
if ($v1 !~ /^(.{1})(.*)$/) {
last; # データが無くなれば15byte未満でもループ終了
}
$v3 = $1; # 抜き出した 1byte をセット
$v1 = $2; # 残りは次の処理に使う
$w1 = hex(unpack "H*", $v3); # 10進数に変換
# 抜き出した 1byte の下位から 2bitずつ見ていく
for ($j = 0; $j < 4; $j++) {
$w2 = $w1; # 論理積計算用に退避
$w2 = $w2 & $v2; # 論理積
$w1 = $w1 >> 2; # 右(下位)に 2bit シフト
print "$i.$j $w2\n";
}
}