perl печатать шестнадцатеричный как удобочитаемый

Файл forsojunk выглядит следующим образом (многие другие строки не показаны).

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

junk.pl заключается в следующем.

#! /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";
}

который дает

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

но я не хочу распечатывать буквальный шестнадцатеричный код, такой как \x27\x27\x27. Я хочу распечатать, как это выглядит, в читаемой форме. В первой строке $2 должно быть напечатано как ''', и все "сообщение" в первой строке должно быть

e''' -> é

Как это сделать?


person Jacob Wegelin    schedule 21.05.2020    source источник


Ответы (2)


Вам нужно преобразовать каждый 2-значный шестнадцатеричный код в печатный символ.

pack работает, или используя цикл с hex для преобразования строки base-16 в число, а затем chr, printf и т. д. для преобразования в соответствующий символ:

#!/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";
    }
}

Пример:

$ perl junk.pl forsojunk
e''' -> é
e' -> é
a_ -> à
person Shawn    schedule 22.05.2020
comment
Что такое m в фигурных скобках вместо s? Признаюсь, я никогда раньше такого не видел. - person Jacob Wegelin; 22.05.2020
comment
@JacobWegelin Regex принимает почти все для разделителей шаблона, но с вещами, отличными от // (косая черта), m, который находится перед ним, не может быть пропущен. Таким образом, m/.../ может быть записано как //, но m{...} должно иметь m. Внутри {} находится просто регулярное выражение для выполнения задания, и оно соответствует $_, которое можно опустить... - person zdim; 22.05.2020
comment
(Re: соответствует $_ --- я имею в виду, что он связывается с $_, поэтому $_ =~ m{...} записывается как m{...}) - person zdim; 22.05.2020
comment
@Шон, какова цель use open qw/IO :locale :std/; в этом скрипте? Вроде работает без него. - person Jacob Wegelin; 23.05.2020
comment
@JacobWegelin Предполагая, что в файле используется та же кодировка символов, что и в вашей текущей локали, он преобразуется из нее во внутренний формат юникода perl и обратно. - person Shawn; 23.05.2020

Вот урезанная версия ответа @Shawn, которая теперь называется 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";
    }
}

пример его работы:

> 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: -> Ö

person Jacob Wegelin    schedule 22.05.2020
comment
Я вернул сдвиг и отправил комментарий, чтобы спросить @Shawn о команде use open qw/IO :locale :std/;, так как он работает без нее. Я уже проголосовал за это. - person Jacob Wegelin; 23.05.2020