バイナリのファイルなどを扱いたい場合や、データの形式を確認するときなどは、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 たい場合や、デー.このコマンドは、私にとってとても利用頻度が高いものです。 というのは、ファイルの形式などを確認するときによく使用するからです。
文字コードを dump するプログラムをつくるということで考えると、漢字の扱いが少々ややこしいです。 漢字を表示する場合、「漢字文字コード」の泣き別れ? が起きないようにすることが必要なためです。
オプション
オプション 説明 -S入力の漢字コードを SJIS として解釈します(nkf と同じ) -E入力の漢字コードを EUC として解釈します(nkf と同じ) -s出力の漢字コードを SJIS とします(nkf と同じ) -e出力の漢字コードを EUC とします(デフォルト)(nkf と同じ) -(10 進数)オフセット指定 10 進数 -0(8 進数)オフセット指定 8 進数 -0x(16 進数)オフセット指定 16 進数
-s, -e, -S, -E を指定しない場合は、漢字の出力は行われません。
使い方は、いたって簡単です。
次の例では、Windows95 のファイルを、入力漢字コード SJIS、出力漢字コード EUC としてファイルの内容をダンプします。
$ hd.rb -S /mnt/dos/Windows/wininit.exe |less
Web ブラウザでの表示上は Ruby のスクリプトですが、HTML の特殊文字をエスケープしています。 テキストとしてセーブしてご利用ください。
#! /usr/local/bin/ruby -Kn
# /home/tetsu/src/ruby/toolbox/hd.rb
# Created: February 22,1998 Sunday 18:39:06
# Author: tetsu(WATANABE Tetsuya)
RCS_ID = %q$Id: hd.rb,v 2.4 2001/08/14 18:23:13 tetsu Exp $
# usage: hd.rb -sE -0100 /vmlinuz | less
def usage
STDERR.print <<E
usage: #$0
[-seSE]
[-(num|0xhex|0oct)]
[files ...]
-[0-9]+ offset decimal
-0[0-7]+ octal
-0x[0-9a-fA-F]+ hex
-S sjis/input code
-E euc /input code
-s sjis/output code
-e euc /output code (default)
#{RCS_ID}
E
exit 1
end
require 'nkf'
class String
def bin_to_str
return self.tr("\177-\377", '.') unless $kanji
w = ($kanji_chip + self).gsub($kanji_re) {
NKF.nkf($nkf_opt_in + 'j', $1)
}.gsub($kana_re) {
NKF.nkf($nkf_opt_in + 'j', $1)
}
w[0,1] = '' if $kanji_chip == w[0,1]
$kanji_chip = if $kanji_chip_re =~ w[-1,1] then w[-1,1] else '' end
NKF.nkf($nkf_opt_out + 'J', w.tr("\177-\377", '.'))
end
end
def hd(f, offset)
if offset > 0
begin
f.pos = offset
rescue
offset = 0
end
end
l_unpackformat = 'N*'
unpackformat = 'N'
l_packformat = 'N*'
packformat = 'N'
dumpformat = '%08x %08x %08x %08x %08x '
dumplastformat = '%8.8x'
back = ''
p_flag = true
while $_ = f.read(16)
break if $_.length != 16
if back == $_
print "*\n" if p_flag
p_flag = false
offset += 16
next
elsif p_flag == false
p_flag = true
end
back = $_
bin = $_.unpack(l_unpackformat)
printf(dumpformat, offset, *bin)
print $_.tr("\000-\037\177", '.').bin_to_str, "\n"
offset += 16
end
unless $_.nil?
n = $_.length / 4
left_byte = $_.length % 4
bin = $_.unpack(unpackformat + n.to_s + 'a' + left_byte.to_s)
n.times {|i| bin[i] = format(dumplastformat, bin[i])}
if left_byte > 0
w = bin[-1].unpack('C*')
foo = ''
w.each_index {|i| foo.concat(format('%2.2x', w[i]))}
bin[-1] = foo + ' ' * (4 - left_byte)
end
(16 / 4 - bin.size).times {bin.push(' ')}
printf(dumpformat.gsub('x', 's'), format('%08x', offset), *bin)
print $_.tr("\000-\037\177", '.').bin_to_str, "\n"
end
end
$kanji = false
$kanji_chip = ''
$nkf_opt_in = '-E'
$nkf_opt_out = '-e'
offset = 0
while $_ = ARGV[0] and ~/^-/
case ARGV.shift
when /^-0([0-7]+)$/
offset = $1.oct
when /^-0x([\da-fA-F]+)$/
offset = $1.hex
when /^-(\d+)$/
offset = $1.to_i
when /^-[se]+$/i
$kanji = true
$nkf_opt_in = '-' + $1 if ~/([SE])/
$nkf_opt_out = '-' + $1 if ~/([se])/
else
usage
end
end
if $nkf_opt_in == '-E'
# - f4ff (less)
$kanji_re = /((?:[\241-\364][\241-\376])+)/n
$kana_re = /((?:\216[\241-\337])+)/n
$kanji_chip_re = /^[\216\241-\376]$/n
else
# 0x81-0x9f 0xe0-0xfc/0x40-0x7e 0x80-0xfc
# 0x40-0x7e 0x80-0xa0 0xe0-0xfc
# - eafc (less)
$kanji_re = /((?:[\201-\237\340-\352][\100-\176\200-\374])+)/n
# kconv/nkf 0xa0-0xdf
$kana_re = /([\241-\337]+)/n
$kanji_chip_re = /^[\201-\237\340-\357]$/n
end
if ARGV.length == 0
hd(STDIN, offset)
else
while file = ARGV.shift
f = File.open(file)
hd(f, offset)
f.close
end
end
exit
$_ のマッチで ~/reg_exp/ 形式への変更に対応