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 '\112'
ou echo $'\112'
. Como imprimo o mesmo caractere por apresentações de pontos de código decimais e hexadecimais?
Responder1
Hex:
printf '\x4a'
Dezembro:
printf "\\$(printf %o 74)"
Alternativa para hexadecimal :-)
xxd -r <<<'0 4a'
Responder2
Em geral, o shell pode entender números hexadecimais, oct e decimais em variáveis, desde que tenham sido definidos 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 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
Então, você só precisa de uma forma de imprimir o caractere que pertence a um valor de 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 o seu console estiver configurado corretamente).
Por exemplo:
$ var=0x2603; printf '%b\n' "\U$(printf '%08x' "$var")"
☃
Um homem de neve.
O caractere que tem uma representação utf-8 como f0 9f 90 ae
está 0x1F42E
. Procure cow face site:fileformat.info
porpegue:
$ var=0x1F42F; printf '%b\n' "\U$(printf '%08x' "$var")"
Responder3
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 sequências:
$ chr 74 75 76; echo
JKL
$
Responder4
Se você tiver uma lista de números para converter e quiser evitar uma chamada de função e criar um subshell para cada caractere, você pode definir o conjunto 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, cada 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"