新井です。 In message "[ruby-list:31983] Re: [ お題 ]文字列の 16進ダンプ" on 21 Oct 2001 17:53:13 +0900, Kazuhiro Yoshida <moriq.kazuhiro / nifty.ne.jp> wrote: > もりきゅうです。 > > Koji Arai <JCA02266 / nifty.ne.jp> wrote: > > ・同じ行の出力は省略したい > > ・日本語出力に対応したい > > これらについて考えてみました。 どうもです(^^。 > ・同じ行の出力は省略したい > > 「行」というのは raw のことでしょうか? です。raw は生文字列の意味で raw ってしたんですがあまりいい 変数名じゃないですね。s ぐらいにするかな。 > -- > 00000000 61626364 65666768 696a6b6c 6d6e6f70 abcdefghijklmnop > 00000010 61626364 65666768 696a6b6c 6d6e6f70 abcdefghijklmnop > 00000020 61626364 65666768 696a6b6c 6d6e6f70 abcdefghijklmnop > 00000030 61626364 65666768 696a6b6c 6d6e6f70 abcdefghijklmnop > > これを > > -- > 00000000 61626364 65666768 696a6b6c 6d6e6f70 abcdefghijklmnop > ..00000030 > > このように表現するようにしてみました。 データサイズがわからなくなるから、最後の行は表示するかどうか したほうがいいんですよねえ。 > ・日本語出力に対応したい > > wordtr(raw) を用意してみました。 > > puts "--", hexdump "abcdefghijklmnoあ" * 4 > -- > 00000000 61626364 65666768 696a6b6c 6d6e6f82 abcdefghijklmno > 00000010 a0616263 64656667 68696a6b 6c6d6e6f .abcdefghijklmno > 00000020 82a06162 63646566 6768696a 6b6c6d6e あabcdefghijklmn > 00000030 6f82a061 62636465 66676869 6a6b6c6d oあabcdefghijklm > 00000040 6e6f82a0 noあ こちらは、日本語の泣き別れにも対応したい(わがままだなあ) 00000000 61626364 65666768 696a6b6c 6d6e6f82 abcdefghijklmnoあ 00000010 a0616263 64656667 68696a6b 6c6d6e6f abcdefghijklmno 00000020 82a06162 63646566 6768696a 6b6c6d6e あabcdefghijklmn 00000030 6f82a061 62636465 66676869 6a6b6c6d oあabcdefghijklm 00000040 6e6f82a0 noあ こんな風がいいかな 基本的にオッケーなんですが、状態保持のための変数が増えるのが 難点です。たとえば、こんなの思い付きました。もっとなんとかエ レガントにできそうな気がしてます(やりすぎ?)。
def hexdump(str) offset = 0 result = [] while raw = str.slice(offset, 16) and raw.length > 0 # data field data = '' for v in raw.unpack('N* a*') if v.kind_of? Integer data << sprintf("%08x ", v) else v.each_byte {|c| data << sprintf("%02x", c) } end end # text field text = raw.tr("\000-\037\177-\377", ".") result << sprintf("%08x %-36s %s", offset, data, text) offset += 16 # omit duplicate line if /^(#{ Regexp.quote(raw) })+/n =~ str[offset .. -1] result << sprintf("%08x ...", offset) offset += $&.length # should print at the end if offset == str.length result << sprintf("%08x %-36s %s", offset-16, data, text) end end end result end puts "--", hexdump "" puts "--", hexdump "a" puts "--", hexdump "abcd" puts "--", hexdump "abcdefghijklmnop" puts "--", hexdump "abcdefghijklmnop" "q" puts "--", hexdump "abcdefghijklmnop" "qrstu" puts "--", hexdump "abcdefghijklmnop" "qrstu" "v" puts "--", hexdump "abcdefghijklmnop" * 4 + "q" puts "--", hexdump "abcdefghijklmnoあ" * 4 # 正規表現コンパイルが高くつくのが難点。 -- 新井康司 (Koji Arai)