「ゲット」できるか? 第二段です。
気がつくところがあればどしどし指摘してください。よろしくお
願いします。
■ Ruby で hex dump
バイナリのファイルなどを扱いたい場合や、データの形式を確認
するときなどは、dump プログラムを使用します。od(1) や
xd(1) (Linux にはないの? と思ったら od -x みたい) と呼ばれ
るものです。ただ、私は od(1) が出力するような形式にはあま
りなじみがありません。Linux の JE などでは jhd が含まれて
います。形式としてはこちらの方が気に入っています(懐かしい
感じです)。
------------------------------
00000000 23 21 20 2F 75 73 72 2F 6C 6F 63 61 6C 2F 62 69 #! /usr/local/bi
00000010 6E 2F 72 75 62 79 0A 23 20 2F 68 6F 6D 65 2F 74 n/ruby.# /home/t
00000020 65 74 73 75 2F 73 72 63 2F 72 75 62 79 2F 68 64 etsu/src/ruby/hd
00000030 2E 72 62 0A 23 20 43 72 65 61 74 65 64 3A 20 46 .rb.# Created: F
00000040 65 62 72 75 61 72 79 20 32 32 2C 31 39 39 38 20 ebruary 22,1998
------------------------------
jhd を使用すれば、漢字コードまで dump の横のエリアに表示で
きてしまうのでとても便利です。
今回作成したものは、次のような出力になります。漢字も扱えま
す。
------------------------------
00000080 75627920 82c52068 65782064 756d700d uby で hex dump.
00000090 0a0d0a83 6f834383 69838a82 cc837483 ...バイナリのフ.
000000a0 40834383 8b82c882 c782f088 b582a282 ァイルなどを扱い.
000000b0 bd82a28f ea8d8782 e2814183 66815b83 たい場合や、デー.
------------------------------
漢字を表示する場合、「漢字文字コード」の泣き別れ? が起きな
いようにするところが少しややこしいです。
使い方は、いたって簡単です。
オプション
-s 入力の漢字コードを SJIS として解釈します
-e 入力の漢字コードを EUC として解釈します
-S 出力の漢字コードを SJIS とします
-E 出力の漢字コードを EUC とします(デフォルト)
入力漢字コードのオプション -s か -e を指定しない場合は、漢
字の出力は行われません。
次の例では、Windows95 のファイルを、入力漢字コード SJIS、
出力漢字コード EUC としてファイルの内容をダンプします。
------------------------------
$ hd.rb -s /mnt/dos/Windows/wininit.exe |less
------------------------------
■ ソースコード
------------------------------
#! /usr/local/bin/ruby
# /home/tetsu/src/ruby/hd.rb
# Created: February 22,1998 Sunday 18:39:06
# Author: tetsu(WATANABE Tetsuya)
# $Id: hd.rb,v 1.3 1998/02/23 15:36:57 tetsu Exp $
# usage:
require "kconv"
include Kconv
def usage
STDERR.print <<E
usage: #$0 [-seSE] [files ...]
-s sjis/input code
-e euc /input code
-S sjis/output code
-E euc /output code (default)
E
exit 1
end
def kstr(bin)
return bin.tr("\200-\377", '.') unless defined? $kanji_re
if $c
bin = $c + bin
$c = nil
over = 1
end
b = bin.split('')
for i in 0 .. b.size - 1
if b[i].size == 2
next if b[i] =~ /#$kanji_re/o
b[i] = if over and i == 0; '.'; else '..' end
elsif b[i].size == 1 and b[i] =~ /[\200-\377]/
$c = b[i] if i == b.size - 1
b[i] = '.'
end
end
b[0] = '.' if over and b[0] == '..'
Kconv.kconv(b.join(''), $lang_out, Kconv::AUTO)
end
$lang_out = Kconv::EUC
while $_ = ARGV[0] and /^-/
ARGV.shift
if /[se]/i
lang_in = if /s/; 'sjis' elsif /e/; 'euc' else nil end
$lang_out = if /S/; Kconv::SJIS elsif /E/; Kconv::EUC end
else
usage
end
end
if lang_in == 'sjis'
$kanji_re = '^[\201-\237\340-\374][\100-\176\200-\374]$'
elsif lang_in == 'euc'
$kanji_re = '^[\241-\376]{2}$'
end
offset = 0
while $_ = $<.read(16)
data = kstr($_.tr("\000-\037\177", '.'))
if $_.length == 16
b = $_.unpack('N4')
printf("%8.8x %8.8x %8.8x %8.8x %8.8x",
offset, *b);
print " ", data, "\n";
offset += 16
else
b = $_.unpack('C*')
for i in 0 .. b.length - 1
b[i] = sprintf('%2.2x', b[i])
end
for i in b.length .. 16 - 1
b.push(' ')
end
printf("%8.8x %s%s%s%s %s%s%s%s %s%s%s%s %s%s%s%s",
offset, *b);
print " ", data, "\n";
break
end
end
exit
------------------------------
--
WATANABE Tetsuya HP Japan PSO
e-mail tetsu / jpn.hp.com