0

I have to convert binary file to ascii values using Perl, which I have to further parse for processing. I did some research and found below code. I can get it to work perfectly but do not understand the code fully. Can anybody please break it down and explain it line by line? P.S: I understand most of the lines, but I am particularly concerned about the part where the actual binary is converted to ascii. Thanks.

foreach $file(@ARGV)
{
    $size= -s $file;
    my $form= length(sprintf("%x",$size))-1;
    ++$form unless $form;
    print "File: ",$file,"\n";
    open (IN,$file);
    while (my $rb= read(IN, $buf, 16))
    {
      my @x= unpack("H2" x $rb, $buf);
      $buf=~ s/[\x00-\x1f\x7f-\xff]/./g;
      $buf.= ' ' x (16-length($buf));
      print $fw ("%0${form}x0: %s [%s]\n"
                 ,$i++,
                 ,sprintf (" %s %s %s %s  %s %s %s %s - %s %s %s %s  %s %s %s %s", @x)
                 ,$buf);
    }
    close (IN)
}
srib
  • 148
  • 2
  • 13
  • 1
    Readup on 'perldoc pack' and 'perldoc unpack'. The syntax for it is a language in itself – Vikhram Feb 03 '16 at 12:39
  • Possible duplicate of [When would you use unpack('h\*' ...) or pack('h\*' ...)?](http://stackoverflow.com/questions/3857499/when-would-you-use-unpackh-or-packh) – tripleee Feb 03 '16 at 12:46
  • That program appears to be buggy. `print $fw ...;` should be `printf ...;`. – ikegami Feb 03 '16 at 15:43
  • But this program works perfectly for me, and achieves my objective. I am able to convert binary to hex dump style format with this script. – srib Feb 11 '16 at 18:10

2 Answers2

2

I think your problem is with the unpack call. I've changed it slightly to this

my @x = unpack '(H2)*', $buf

The format specifier (H2)* says to convert each byte of the string in the second parameter to a two-digit hex number. The * just means to convert as many bytes as there are in the string

This will work properly for you

use strict;
use warnings 'all';

use POSIX 'ceil';

for my $file (@ARGV) {

    my $size = 16 * ceil( (-s $file) / 16);

    my $form = length sprintf '%x', $size-1;
    $form ||= 1;

    print "File: $file\n";
    open my $fh, '<', $file or die $!;

    my $i = 0;
    while ( my $rb = read $fh, my $buf, 16 ) {

      my @x = unpack '(H2)*', $buf;
      push @x, '  ' until @x == 16;

      $buf =~ tr/\x20-\x7E/./c;

      $buf .= ' ' x (16 - length($buf));

      printf "%0*x: %s [%s]\n",
          $form,
          $i++,
          sprintf( "%s %s %s %s  %s %s %s %s - %s %s %s %s  %s %s %s %s", @x ),
          $buf;
    }

    print "\n";
}

output

Here it is dumping itself

File: E:\Perl\source\hexdump.pl
000: 75 73 65 20  73 74 72 69 - 63 74 3b 0a  75 73 65 20 [use strict;.use ]
001: 77 61 72 6e  69 6e 67 73 - 20 71 77 2f  20 61 6c 6c [warnings qw/ all]
002: 20 46 41 54  41 4c 20 2f - 3b 0a 0a 75  73 65 20 50 [ FATAL /;..use P]
003: 4f 53 49 58  20 27 63 65 - 69 6c 27 3b  0a 0a 40 41 [OSIX 'ceil';..@A]
004: 52 47 56 20  3d 20 24 30 - 3b 0a 0a 66  6f 72 20 6d [RGV = $0;..for m]
005: 79 20 24 66  69 6c 65 20 - 28 40 41 52  47 56 29 20 [y $file (@ARGV) ]
006: 7b 0a 0a 20  20 20 20 6d - 79 20 24 73  69 7a 65 20 [{..    my $size ]
007: 3d 20 31 36  20 2a 20 63 - 65 69 6c 28  20 28 2d 73 [= 16 * ceil( (-s]
008: 20 24 66 69  6c 65 29 20 - 2f 20 31 36  29 3b 0a 0a [ $file) / 16);..]
009: 20 20 20 20  6d 79 20 24 - 66 6f 72 6d  20 3d 20 6c [    my $form = l]
00a: 65 6e 67 74  68 20 73 70 - 72 69 6e 74  66 20 27 25 [ength sprintf '%]
00b: 78 27 2c 20  24 73 69 7a - 65 2d 31 3b  0a 20 20 20 [x', $size-1;.   ]
00c: 20 24 66 6f  72 6d 20 7c - 7c 3d 20 31  3b 0a 0a 20 [ $form ||= 1;.. ]
00d: 20 20 20 70  72 69 6e 74 - 20 22 46 69  6c 65 3a 20 [   print "File: ]
00e: 24 66 69 6c  65 5c 6e 22 - 3b 0a 20 20  20 20 6f 70 [$file\n";.    op]
00f: 65 6e 20 6d  79 20 24 66 - 68 2c 20 27  3c 27 2c 20 [en my $fh, '<', ]
010: 24 66 69 6c  65 20 6f 72 - 20 64 69 65  20 24 21 3b [$file or die $!;]
011: 0a 0a 20 20  20 20 6d 79 - 20 24 69 20  3d 20 30 3b [..    my $i = 0;]
012: 0a 20 20 20  20 77 68 69 - 6c 65 20 28  20 6d 79 20 [.    while ( my ]
013: 24 72 62 20  3d 20 72 65 - 61 64 20 24  66 68 2c 20 [$rb = read $fh, ]
014: 6d 79 20 24  62 75 66 2c - 20 31 36 20  29 20 7b 0a [my $buf, 16 ) {.]
015: 0a 20 20 20  20 20 20 6d - 79 20 40 78  20 3d 20 75 [.      my @x = u]
016: 6e 70 61 63  6b 20 27 28 - 48 32 29 2a  27 2c 20 24 [npack '(H2)*', $]
017: 62 75 66 3b  0a 20 20 20 - 20 20 20 70  75 73 68 20 [buf;.      push ]
018: 40 78 2c 20  27 20 20 27 - 20 75 6e 74  69 6c 20 40 [@x, '  ' until @]
019: 78 20 3d 3d  20 31 36 3b - 0a 0a 20 20  20 20 20 20 [x == 16;..      ]
01a: 24 62 75 66  20 3d 7e 20 - 74 72 2f 5c  78 32 30 2d [$buf =~ tr/\x20-]
01b: 5c 78 37 45  2f 2e 2f 63 - 3b 0a 0a 20  20 20 20 20 [\x7E/./c;..     ]
01c: 20 24 62 75  66 20 2e 3d - 20 27 20 27  20 78 20 28 [ $buf .= ' ' x (]
01d: 31 36 20 2d  20 6c 65 6e - 67 74 68 28  24 62 75 66 [16 - length($buf]
01e: 29 29 3b 0a  0a 20 20 20 - 20 20 20 70  72 69 6e 74 [));..      print]
01f: 66 20 22 25  30 2a 78 3a - 20 25 73 20  5b 25 73 5d [f "%0*x: %s [%s]]
020: 5c 6e 22 2c  0a 20 20 20 - 20 20 20 20  20 20 20 24 [\n",.          $]
021: 66 6f 72 6d  2c 0a 20 20 - 20 20 20 20  20 20 20 20 [form,.          ]
022: 24 69 2b 2b  2c 0a 20 20 - 20 20 20 20  20 20 20 20 [$i++,.          ]
023: 73 70 72 69  6e 74 66 28 - 20 22 25 73  20 25 73 20 [sprintf( "%s %s ]
024: 25 73 20 25  73 20 20 25 - 73 20 25 73  20 25 73 20 [%s %s  %s %s %s ]
025: 25 73 20 2d  20 25 73 20 - 25 73 20 25  73 20 25 73 [%s - %s %s %s %s]
026: 20 20 25 73  20 25 73 20 - 25 73 20 25  73 22 2c 20 [  %s %s %s %s", ]
027: 40 78 20 29  2c 0a 20 20 - 20 20 20 20  20 20 20 20 [@x ),.          ]
028: 24 62 75 66  3b 0a 20 20 - 20 20 7d 0a  0a 20 20 20 [$buf;.    }..   ]
029: 20 70 72 69  6e 74 20 22 - 5c 6e 22 3b  0a 7d       [ print "\n";.}  ]
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thanks for your answer. In the while loop, can you explain what is happening step-by-step? – srib Feb 11 '16 at 18:19
  • @srib: It's inappropriate to solve extensive problems like that in comments. There is nothing there that isn't standard Perl, so you should read [the documentation](http://perldoc.perl.org/) – Borodin Feb 18 '16 at 02:06
  • @Borodin This is the kind of attitude that has kept the Perl community getting smaller every day. While you are right in your response, and you are giving a helpful answer, putting teaching/explanatory comments in your code lines to help someone with little knowledge learn from it, even more when he is explicitly asking for help understanding it, would be a much more friendly way to help him an others. Just my point of view. And yes, I know this is a four year old response, but still. – Francisco Zarabozo Jun 13 '20 at 17:12
1

Binary isn't used, and there's no conversion to ASCII.

The program displays the hex representation of each byte of the file. At its core is unpack 'H2', $byte, which returns the hex representation of a byte.

It also displays the ASCII representation of those bytes. The program does not need to do any conversion to do this. The bytes are simply sent to the terminal which maps them to glyphs.

ikegami
  • 367,544
  • 15
  • 269
  • 518