From time to time, I saw people wondering why a piece of code does not work, just because they have “garbage” in their data. People really need a tool to inspect what their strings contain, so I just created this StringInspector class, and hope it helps.

This is how to use it:
use StringInspector; use strict; my $inspector = new StringInspector; $inspector->inspect("abcdefghijkl"); $inspector->display();
This is the package itself:
package StringInspector; use Hash::Util qw(lock_keys); use strict; sub new { my $self = {}; $self->{SUSPECT} = ""; bless $self; lock_keys(%{$self}); return $self; } sub inspect { my ($self, $string) = @_; $self->{SUSPECT} = $string; } sub display { my $self = shift; for (my $index = 0; $index <= length $self->{SUSPECT}; $index += 1 +0) { my $ten= substr($self->{SUSPECT}, $index, 10); my $numbers = ""; my $chars = ""; for (my $this_char = 0; $this_char < length $ten; $this_char + ++) { my $ascii = ord(substr($ten, $this_char, 1)); $numbers .= sprintf("0x%0x ", $ascii); $chars .= (($ascii >= 32) && ($ascii <= 126)) ? substr($te +n, $this_char, 1) : "."; } print $numbers; print " " x (60 - length $numbers); print " " x 5; print $chars; print "\n"; } } 1;

Replies are listed 'Best First'.
Re: Is there any garbage chars in your data?
by cchampion (Curate) on Mar 26, 2003 at 00:04 UTC

    Wouldn't this be a lot quicker and simpler?

    #!/usr/bin/perl -w use strict; my $string = "abc12defghi\013jkl"; for (split //, $string) { print /[[:print:]]/ ? $_ : sprintf " (0x%02x) ", ord $_ ; } print "\n"; __END__ abc12defghi (0x0b) jkl
      Thank you, modified my code to include your split //. However, I choose not to use :print:, as that would have problem with Unicode, instead I added ‘use bytes’ to my code.

      I still like my own output format better ;-), but I added code to allow user to configure the format (a little bit).
      package StringInspector; use Hash::Util qw(lock_keys); use strict; sub new { my $self = {}; $self->{SUSPECT} = ""; $self->{BYTES_IN_ROW} = 10; $self->{COLUMNS_BETWEEN_PANES} = 5; bless $self; lock_keys(%{$self}); return $self; } sub inspect { my ($self, $string) = @_; $self->{SUSPECT} = $string; } sub bytes_in_row { my $self = shift; if (@_) { $self->{BYTES_IN_ROW} = shift; } return $self->{BYTES_IN_ROW}; } sub columns_between_panes { my $self = shift; if (@_) { $self->{COLUMNS_BETWEEN_PANES} = shift; } return $self->{COLUMNS_BETWEEN_PANES}; } sub display { use bytes; my $self = shift; for (my $index = 0; $index <= length $self->{SUSPECT}; $index += $ +self->{BYTES_IN_ROW}) { my ($numbers, $chars) = ("", ""); foreach my $this_char (split(//, substr($self->{SUSPECT}, $ind +ex, $self->{BYTES_IN_ROW}))) { my $ascii = ord($this_char); $numbers .= sprintf("0x%0x ", $ascii); $chars .= (($ascii >= 32) and ($ascii <= 126)) ? $this_cha +r : "."; } print $numbers; print " " x (6 * $self->{BYTES_IN_ROW} - length $numbers); print " " x $self->{COLUMNS_BETWEEN_PANES}; print $chars; print "\n"; } } 1; testing code: use StringInspector; use strict; my $inspector = new StringInspector; $inspector->bytes_in_row(3); $inspector->columns_between_panes(40); $inspector->inspect("abcdefghi" . chr(400) ."jkl"); $inspector->display();