Как напечатать символ ASCII по разным кодовым точкам в Bash?

Как напечатать символ ASCII по разным кодовым точкам в Bash?

В таблице ASCII существует символ «J», имеющий кодовые точки в разных системах счисления:

Oct   Dec   Hex   Char
112   74    4A    J

Можно напечатать этот символ по восьмеричной кодовой точке, напечатав printf '\112'или echo $'\112'. Как напечатать тот же символ по десятичной и шестнадцатеричной кодовой точке?

решение1

Шестнадцатеричный код:

printf '\x4a'

Дек:

printf "\\$(printf %o 74)"

Альтернатива hex :-)

xxd -r <<<'0 4a'

решение2

В общем случае оболочка может понимать шестнадцатеричные, восьмеричные и десятичные числа в переменных, при условии, что они определены следующим образом 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

Или они являются результатом «арифметического расширения»:

$ : $(( 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

Итак, вам просто нужен один способ напечатать символ, который принадлежит значению переменной.
Но вот два возможных способа:

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

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

Необходимы две функции printf: одна для преобразования значения в шестнадцатеричную строку, а вторая — для фактической печати символа.

Второй выведет любую точку UNICODE (если ваша консоль настроена правильно).
Например:

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

Снежный человек.

Символ, который имеет представление utf-8, как f0 9f 90 aeесть 0x1F42E. Поиск cow face site:fileformat.infoповозьми:

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

решение3

Десятичная дробь:

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

chr 74

Шестнадцатеричный код:

chr $((16#4a))

Функция может выполнять последовательности:

$ chr 74 75 76; echo
JKL
$

решение4

Если у вас есть список чисел для преобразования и вы хотите избежать вызова функции и создания подоболочки для каждого символа, вы можете заранее определить набор ASCII:

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

Обратите внимание, что нулевой символ исключается, поэтому каждый символ смещается на 1.

Затем используйте что-то вроде этого (предполагается, что в каждой строке по одному числу):

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

Связанный контент