Como imprimo um caractere ASCII por diferentes pontos de código no Bash?

9

Na tabela ASCII existe o caractere 'J' que possui pontos de código em diferentes sistemas numéricos:

Oct   Dec   Hex   Char
112   74    4A    J

É possível imprimir este caractere por um ponto de código octal imprimindo printf '2' ou echo $'2' . Como faço para imprimir o mesmo caractere por apresentações de pontos de código decimais e hexadecimais?

    
por viavad 23.09.2016 / 18:09

6 respostas

10

Hex:

printf '\x4a'

Dez:

printf "\$(printf %o 74)"

Alternativa para hexadecimal: -)

xxd -r <<<'0 4a'
    
por 23.09.2016 / 18:17
5

com zsh :

$ printf '\x4a\n' # Hex
J
$ printf "\$(([##8]74))\n" # Dec
J

Para obter um caractere (no conjunto de caracteres atual) do ponto de código Unicode:

$ printf '\U1F42E\n' # Hex
                                    
por 23.09.2016 / 18:25
5

Em geral, o shell pode entender números hexadecimais, oct e decimais em variáveis, desde que tenham sido definidas como integers :

$ declare -i v1 v2 v3 v4 v5 v6 v7
$ v1=0112
$ v2=74
$ v3=0x4a
$ v4=8#112
$ v5=10#74
$ v6=16#4a
$ v7=18#gg
echo "$v1 $v2 $v3 $v4 $v5 $v6 $v7"
74 74 74 74 74 74 304

Ou eles são o resultado de uma "Expansão Aritmética":

$ : $(( v1=0112, v2=74, v3=0x4a, v4=8#112, v5=10#74, v6=16#4a, v7=18#gg ))
$ echo "$v1 $v2 $v3 $v4 $v5 $v6 $v7"
74 74 74 74 74 74 304

Assim, você só precisa de uma maneira de imprimir o caractere que pertence a um valor variável.
Mas aqui estão duas maneiras possíveis:

$ var=$((0x65))
$ printf '%b\n' "\$(printf '0%o' "$var")"
e

$ declare -i var
$ var=0x65; printf '%b\n' "\U$(printf '%08x' "$var")"
e

Os dois printf são necessários, um para transformar o valor em uma string hexadecimal e o segundo para realmente imprimir o caractere.

O segundo imprimirá qualquer ponto UNICODE (se seu console estiver configurado corretamente). Por exemplo:

$ var=0x2603; printf '%b\n' "\U$(printf '%08x' "$var")"
☃

Um homem da neve.

O caractere que possui uma representação utf-8 como f0 9f 90 ae é 0x1F42E . Pesquise cow face site:fileformat.info para acesse :

$ var=0x1F42F; printf '%b\n' "\U$(printf '%08x' "$var")"
                                    
por 24.09.2016 / 02:32
4

decimal:

chr() {
    local c
    for c
    do
        printf "\$((c/64*100+c%64/8*10+c%8))"
    done
}

chr 74

Hex:

chr $((16#4a))

A função pode fazer seqüências:

$ chr 74 75 76; echo
JKL
$
    
por 23.09.2016 / 19:03
0

Você pode usar a biblioteca stdlib do POSIX :

$ awklib 'BEGIN {print str_chr(74)}'
J

$ awklib 'BEGIN {print str_chr(+base_conv("4A", 16, 10))}'
J

$ awklib 'BEGIN {print str_chr(+base_conv(112, 8, 10))}'
J

$ awklib 'BEGIN {print str_chr(+base_conv(1001010, 2, 10))}'
J
    
por 29.03.2017 / 02:34
0

Se você tem uma lista de números para converter, e quer evitar uma chamada de função e criar uma sub-tampa para cada personagem, você pode definir o conjunto de ascii de antemão:

ascii=$(for x in {0..9} {A..F}; do for y in {0..9} {A..F}; do echo -ne "\x$x$y"; done; done)

Observe que o caractere nulo é excluído, portanto, todo caractere é compensado por 1.

Em seguida, use algo assim (assume 1 número por linha):

while read c; do out+="${ascii:$c-1:1}"; done <<< "$in"
echo "$out"
    
por 27.04.2018 / 17:17