From: Todd Burch Date: 2007-05-11T01:39:36+09:00 Subject: Re: Trouble using string.tr() Here a whole program that illlustrates the error. I'm running under Windows Ruby 1.8.5. (it's ugly and chopped up, but it works... er... doesn't work... er... you know what I mean) Todd # # Ruby program to convert a z/OS EBCDIC to ASCII. # class Record # # The Record.report_values() method used the Record Layout info and parses a record at a time, building the output ASCII row. # def Record.report_values(edata) ; # ebcdic data adata = edata.tr($ebcdic_chars, $ascii_chars) ; # ascii data puts "ebcdic data = #{edata}" ; puts ; puts "ascii data = #{adata}" ; puts ; end ; # def report_values # # This Record.to_h() method converts a hex byte into a displayable, human readable value. i.e. X'F5' to "F5". # def Record.to_h(str) str.unpack('H64').to_s.upcase ; end ; # # This method called to dump the data in hex format. # def Record.dump_area(data) ; fsize = data.size ; lines,last = fsize.divmod(32) # get # of full lines and figure the remainder. i = 0 while lines > 0 str = data[i..i+31] hexdata = Record.to_h(str) # .unpack('H64').to_s.upcase printf( "%08X %8s %8s %8s %8s %8s %8s %8s %8s %s\n", i, hexdata[0..7], hexdata[8..15], hexdata[16..23], hexdata[24..31], hexdata[32..39], hexdata[40..47], hexdata[48..55], hexdata[56..63], str.tr("\000-\037\177-\377",'.')) i += 32; lines -= 1 end # Write out the partial line. str = data[i..fsize] line = sprintf("%08x ",i) i.upto(fsize) {|x| line << sprintf("%2s",data[x..x].unpack('H2').to_s.upcase) if (((x+1)% 4)==0) then line << " " end if (((x+1)%16)==0) then line << " " end } line << " "*(2+90-line.length) line << sprintf("%s\n", str.tr("\000-\037\177-\377",'.')) printf(line) end ; end ; # class Record. This is the end of all the method defintions for class Record. def doit(data) ; # # Now starts the translate table definitions. They are order-sensitive. Do not change the order unless you have a real reason to. # # $ebcdic_chars (global variable) is the "from string" portion of the translate process. # $ascii_chars is the "to string" portion. # # $ebcdic_nums is the "from string" for converting from X'F0' through X'F9' (0-9 ebcdic) # $ascii_nums is the "to string" for converting to X'30' through X'39' (0-9 ascii) # $ebcdic_chars = 0x40.chr ; # blank ###$ebcdic_chars += 0xFF.chr ; # unprintable ###$ebcdic_chars += 0x00.chr ; # unprintable $ebcdic_chars += 0XC1.chr + 0xC2.chr + 0xC3.chr + 0xC4.chr + 0xC5.chr + 0xC6.chr + 0xC7.chr + 0xC8.chr + 0xC9.chr ; # A-I $ebcdic_chars += 0XD1.chr + 0xD2.chr + 0xD3.chr + 0xD4.chr + 0xD5.chr + 0xD6.chr + 0xD7.chr + 0xD8.chr + 0xD9.chr ; # J-R $ebcdic_chars += 0xE2.chr + 0xE3.chr + 0xE4.chr + 0xE5.chr + 0xE6.chr + 0xE7.chr + 0xE8.chr + 0xE9.chr ; # S-Z $ebcdic_chars += 0X81.chr + 0x82.chr + 0x83.chr + 0x84.chr + 0x85.chr + 0x86.chr + 0x87.chr + 0x88.chr + 0x89.chr ; # a-i $ebcdic_chars += 0X91.chr + 0x92.chr + 0x93.chr + 0x94.chr + 0x95.chr + 0x96.chr + 0x97.chr + 0x98.chr + 0x99.chr ; # j-r $ebcdic_chars += 0xA2.chr + 0xA3.chr + 0xA4.chr + 0xA5.chr + 0xA6.chr + 0xA7.chr + 0xA8.chr + 0xA9.chr ; # s-z $ebcdic_chars += 0x4B.chr ; # . $ebcdic_chars += 0x4C.chr ; # < $ebcdic_chars += 0x4D.chr ; # ( $ebcdic_chars += 0x4E.chr ; # + $ebcdic_chars += 0x4F.chr ; # | $ebcdic_chars += 0x50.chr ; # & $ebcdic_chars += 0x5A.chr ; # ! $ebcdic_chars += 0x5B.chr ; # $ $ebcdic_chars += 0x5C.chr ; # * $ebcdic_chars += 0x5D.chr ; # ) $ebcdic_chars += 0x5E.chr ; # ; $ebcdic_chars += 0x5F.chr ; # ^ $ebcdic_chars += 0x60.chr ; # - $ebcdic_chars += 0x61.chr ; # / $ebcdic_chars += 0x6B.chr ; # , $ebcdic_chars += 0x6C.chr ; # % $ebcdic_chars += 0x6D.chr ; # _ $ebcdic_chars += 0x6E.chr ; # > $ebcdic_chars += 0x6F.chr ; # ? $ebcdic_chars += 0X79.chr ; # ` $ebcdic_chars += 0x7A.chr ; # : $ebcdic_chars += 0x7B.chr ; # # $ebcdic_chars += 0x7C.chr ; # @ $ebcdic_chars += 0x7D.chr ; # ' $ebcdic_chars += 0x7E.chr ; # = $ebcdic_chars += 0x7F.chr ; # " $ebcdic_chars += 0xBA.chr ; # [ $ebcdic_chars += 0xBB.chr ; # ] $ebcdic_chars += 0xC0.chr ; # { $ebcdic_chars += 0xD0.chr ; # } $ebcdic_chars += 0xE0.chr ; # \ $ascii_chars = " " ; # blank ###$ascii_chars += " " ; # make ebcdic 0XFF into a blank ###$ascii_chars += ' ' ; # make ebcdic 0X00 into a blank $ascii_chars += ('A'..'Z').to_a.to_s ; # A-Z $ascii_chars += ('a'..'z').to_a.to_s ; # a-z $ascii_chars += '.' ; $ascii_chars += '<' ; $ascii_chars += '(' ; $ascii_chars += '+' ; $ascii_chars += '|' ; $ascii_chars += '&' ; $ascii_chars += '!' ; $ascii_chars += '$' ; $ascii_chars += '*' ; $ascii_chars += ')' ; $ascii_chars += ';' ; $ascii_chars += '^' ; $ascii_chars += '-' ; $ascii_chars += '/' ; $ascii_chars += ',' ; $ascii_chars += '%' ; $ascii_chars += '_' ; $ascii_chars += '>' ; $ascii_chars += '?' ; $ascii_chars += '`' ; $ascii_chars += ':' ; $ascii_chars += '#' ; $ascii_chars += '@' ; $ascii_chars += '\''; $ascii_chars += '=' ; $ascii_chars += '"' ; $ascii_chars += '[' ; $ascii_chars += ']' ; $ascii_chars += '{' ; $ascii_chars += '}' ; $ascii_chars += '\\' ; # escape char is special - must be doubled $ebcdic_nums = 0xF0.chr + 0XF1.chr + 0xF2.chr + 0xF3.chr + 0xF4.chr + 0xF5.chr + 0xF6.chr + 0xF7.chr + 0xF8.chr + 0xF9.chr ; $ascii_nums = "0123456789" ; $ebcdic_chars += $ebcdic_nums ; $ascii_chars += $ascii_nums ; # true if the record was as expected, or false if not. Record.report_values(data) Record.dump_area( data ) ; # write offending record, in hex dump format, to the INVALID_FORMAT file. end ; # def doit() instring = 0XC1.chr + 0xC2.chr + 0x6E.chr + 0xC1.chr + 0xC1.chr + 0x4C.chr + 0xC1.chr + 0xC3.chr ; # EBCDIC for "AB>AA