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)
}
4
  • 1
    Readup on 'perldoc pack' and 'perldoc unpack'. The syntax for it is a language in itself Commented Feb 3, 2016 at 12:39
  • Possible duplicate of When would you use unpack('h*' ...) or pack('h*' ...)? Commented Feb 3, 2016 at 12:46
  • That program appears to be buggy. print $fw ...; should be printf ...;. Commented Feb 3, 2016 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. Commented Feb 11, 2016 at 18:10

2 Answers 2

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";.}  ]
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. In the while loop, can you explain what is happening step-by-step?
@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
@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.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.