perl print hexadecimal as human-readable

523 Views Asked by At

File forsojunk is as follows (with many more lines not shown).

    s/e\x27\x27\x27/é/g; 
    s/e\x27/é/g; 
    s/a\x5f/à/g; 

junk.pl is as follows.

#! /usr/bin/perl
use strict; use warnings;
while(<>) {
   $_ =~ s/s\x2f([^\x2f\x5c]+)([^\x2f]*)\x2f([^\x2f]*).*/1=$1; 2=$2; 3=$3/ ;
   print $1;
   print $2;
   print " -> ";
   print $3;
   print "\n";
}

which gives

> junk.pl forsojunk
e\x27\x27\x27 -> é
e\x27 -> é
a\x5f -> ò

but I do not want to print out the literal hex code such as \x27\x27\x27. I want to print out what it looks like, the readable form. At the first line, $2 should print out as ''' and the entire "message" in the first line should be

e''' -> é

How does one accomplish this?

2

There are 2 best solutions below

5
Shawn On BEST ANSWER

You need to convert each 2-digit hexcode to a printable character.

pack works, or using a loop with hex to convert from a base-16 string to a number, and then chr, printf, etc to convert to the corresponding character:

#!/usr/bin/env perl
use strict;
use warnings;
use open qw/IO :locale :std/;

while(<>) {
    # Note the cleaned up regular expression
    if (my ($base, $rawaddons, $result) = m{s/([^/\\]+)([^/]*)/([^/]*)/}) {
        my @addons = split/\\x/, $rawaddons; # Split up the hexcodes and remove the \\x parts
        shift @addons; # Drop the first empty element
        print $base;
        # Any of the below ways work
        print pack('(H2)*', @addons);
        # printf '%c', hex for @addons;
        # print map { chr hex } @addons;
        print " -> $result\n";
    }
}

Example:

$ perl junk.pl forsojunk
e''' -> é
e' -> é
a_ -> à
1
Jacob Wegelin On

Here is a pared-down version of @Shawn's answer, now named bbb.pl.

#!/usr/bin/env perl
use strict; use warnings;
while(<>) {
   if (my ($base, $rawaddons, $result) = m{s/([^/\\]+)([^/]*)/([^/]*)/}) {
        my @addons = split/\\x/, $rawaddons; # Split up the hexcodes and remove the \\x parts
        shift @addons; #first element is blank or null       
        print $base;
        print pack('(H2)*', @addons);
        print " -> $result\n";
    }
}

example of it running:

> cat forsojunk
    s/\x3c/\x5ctextless{}/g; # < becomes \textless{}
    s/a\x27\x27\x27/á/g; #2020v05v21vThuv17h26m54s
    s/e\x27\x27\x27/é/g; #2020v05v21vThuv17h26m54s
    s/i\x27\x27\x27/í/g; #2020v05v21vThuv17h26m54s
    s/o\x27\x27\x27/ó/g; #2020v05v21vThuv17h26m54s
    s/u\x27\x27\x27/ú/g; #2020v05v21vThuv17h26m54s
    s/A\x27\x27\x27/Á/g; #2020v05v21vThuv17h26m54s
    s/E\x27\x27\x27/É/g; #2020v05v21vThuv17h26m54s
    s/I\x27\x27\x27/Í/g; #2020v05v21vThuv17h26m54s
    s/O\x27\x27\x27/Ó/g; #2020v05v21vThuv17h26m54s
    s/U\x27\x27\x27/Ú/g; #2020v05v21vThuv17h26m54s
    s/e\x60/è/g;
    s/E\x60/È/g;
    s/a\x60/à/g;
    s/A\x60/À/g;
    s/i\x5e/î/g;
    s/I\x5e/Î/g;
    s/o\x5e/ô/g;
    s/O\x5e/Ô/g;
    s/u\x3a/ü/g;
    s/U\x3a/Ü/g;
    s/a\x3a/ä/g;
    s/A\x3a/Ä/g;
    s/o\x3a/ö/g;
    s/O\x3a/Ö/g;
> bbb.pl forsojunk
a''' -> á
e''' -> é
i''' -> í
o''' -> ó
u''' -> ú
A''' -> Á
E''' -> É
I''' -> Í
O''' -> Ó
U''' -> Ú
e` -> è
E` -> È
a` -> à
A` -> À
i^ -> î
I^ -> Î
o^ -> ô
O^ -> Ô
u: -> ü
U: -> Ü
a: -> ä
A: -> Ä
o: -> ö
O: -> Ö