Как вы эхо 4-значный символ Юникода в Bash?

Я хотел бы добавить череп и скрещенные кости Юникода в мою подсказку оболочки (в частности, "ЧЕРЕП И КРЕСТЫ" (U + 2620)), но я не могу понять магическое заклинание, которое заставило бы эхо выплюнуть его или любое другое, 4-значный Unicode символ. Двузначные легко. Например, echo -e "\ x55",.

В дополнение к ответам ниже следует отметить, что, очевидно, ваш терминал должен поддерживать Unicode, чтобы вывод был тем, что вы ожидаете. gnome-терминал хорошо справляется с этой задачей, но он не обязательно включен по умолчанию.

В приложении MacOS Terminal перейдите в Preferences-> Кодировки и выберите Unicode (UTF-8).

Ответ 1

В UTF-8 это фактически 6 цифр (или 3 байта).

$ printf '\xE2\x98\xA0'
☠

Чтобы проверить, как это кодируется консолью, используйте hexdump:

$ printf ☠ | hexdump
0000000 98e2 00a0                              
0000003

Ответ 2

% echo -e '\u2620'     # \u takes four hexadecimal digits
☠
% echo -e '\U0001f602' # \U takes eight hexadecimal digits
😂

Это работает в Zsh (я проверял версию 4.3) и в Bash 4.2 или новее.

Ответ 3

До тех пор, пока ваши текстовые редакторы могут справляться с Unicode (предположительно, закодированы в UTF-8), вы можете вводить кодовую точку Unicode напрямую.

Например, в текстовом редакторе Vim вы должны войти в режим вставки и нажать Ctrl + V + U, а затем номер кодовой точки в виде 4-значного шестнадцатеричного числа (при необходимости, с нулями). Поэтому вы должны набрать Ctrl + V + U 2 6 2 0. См.: Какой самый простой способ вставить символы Unicode в документ?

В терминале, на котором запущен Bash, вы должны набрать CTRL + SHIFT + U и ввести шестнадцатеричный код нужного вам символа. Во время ввода ваш курсор должен показывать подчеркнутый u. Первый не набираемый вами номер завершает ввод и отображает символ. Таким образом, вы можете печатать U + 2620 в Bash, используя следующее:

e c h o CTRL + SHIFT + U 2 6 2 0 ENTER ENTER

(Первый ввод завершает ввод Unicode, а второй запускает команду echo.)

Кредит: Спросите Ubuntu SE

Ответ 4

Здесь полная внутренняя реализация Bash, без разветвления, неограниченный размер символов Юникода.

fast_chr() {
    local __octal
    local __char
    printf -v __octal '%03o' $1
    printf -v __char \\$__octal
    REPLY=$__char
}

function unichr {
    local c=$1    # Ordinal of char
    local l=0    # Byte ctr
    local o=63    # Ceiling
    local p=128    # Accum. bits
    local s=''    # Output string

    (( c < 0x80 )) && { fast_chr "$c"; echo -n "$REPLY"; return; }

    while (( c > o )); do
        fast_chr $(( t = 0x80 | c & 0x3f ))
        s="$REPLY$s"
        (( c >>= 6, l++, p += o+1, o>>=1 ))
    done

    fast_chr $(( t = p | c ))
    echo -n "$REPLY$s"
}

## test harness
for (( i=0x2500; i<0x2600; i++ )); do
    unichr $i
done

Выход был:

─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿

Ответ 5

Просто вставьте "☠" в свой скрипт оболочки. В правильной локали и на консоли с поддержкой Unicode он будет печататься очень хорошо:

$ echo ☠
☠
$

Уродливым "обходным путем" может быть вывод последовательности UTF-8, но это также зависит от используемой кодировки:

$ echo -e '\xE2\x98\xA0'
☠
$

Ответ 6

Быстрый однострочный перевод для преобразования символов UTF-8 в их 3-байтовый формат:

var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo

Ответ 7

Я использую это:

$ echo -e '\u2620'
☠

Это довольно просто, чем поиск в шестнадцатеричном представлении... Я использую это в своих скриптах оболочки. Это работает на gnome-term и urxvt AFAIK.

Ответ 8

Вам может потребоваться кодировать кодовую точку как восьмеричную, чтобы быстрое расширение могло правильно декодировать ее.

U + 2620, кодированный как UTF-8, является E2 98 A0.

Итак, в Bash,

export PS1="\342\230\240"

сделает запрос оболочки черепом и костями.

Ответ 9

Любая из этих трех команд будет печатать символ, который вы хотите в консоли, если консоль принимает UTF-8 символы (самые последние делать):

echo -e "SKULL AND CROSSBONES (U+2620) \U02620"
echo $'SKULL AND CROSSBONES (U+2620) \U02620'
printf "%b" "SKULL AND CROSSBONES (U+2620) \U02620\n"

SKULL AND CROSSBONES (U+2620) ☠

После этого вы можете скопировать и вставить фактический глиф (изображение, символ) в любой текстовый редактор с поддержкой UTF-8.

Если вам нужно увидеть, как такая кодовая точка Юникода закодирована в UTF-8, используйте xxd (гораздо лучше hex viewer, чем od):

echo $'(U+2620) \U02620' | xxd
0000000: 2855 2b32 3632 3029 20e2 98a0 0a         (U+2620) ....

That means that the UTF8 encoding is: e2 98 a0

Или, в HEX, чтобы избежать ошибок: 0xE2 0x98 0xA0. То есть значения между пространством (HEX 20) и линией подачи (Hex 0A).

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

Ответ 10

В bash для вывода символа Unicode для вывода используйте \x,\u или\U (сначала для шестнадцатеричного шестнадцатеричного числа, второго для шестнадцатеричного шестнадцатеричного числа, третьего для любой длины)

echo -e '\U1f602'

Если вы хотите присвоить его переменной, используйте синтаксис $ '...'

x=$'\U1f602'
echo $x

Ответ 11

Встроенный printf (так же как coreutils 'printf) знает escape-последовательность \u, которая принимает четырехзначные символы Unicode:

   \uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)

Тест с Bash 4.2.37 (1):

$ printf '\u2620\n'
☠

Ответ 12

Если вы не против однострочного Perl:

$ perl -CS -E 'say "\x{2620}"'
☠

-CS позволяет декодировать UTF-8 на входе и кодировку UTF-8 на выходе. -E оценивает следующий аргумент как Perl, с такими современными функциями, как say. Если вы не хотите использовать новую строку в конце, используйте print вместо say.

Ответ 13

Извините за возрождение этого старого вопроса. Но при использовании bash существует очень простой подход для создания кодовых точек Unicode из простого ввода ASCII, который даже не разветвляется:

unicode() { local -n a="$1"; local c; printf -vc '\\U%08x' "$2"; printf -va "$c"; }
unicodes() { local a c; for a; do printf -vc '\\U%08x' "$a"; printf "$c"; done; };

Используйте его следующим образом для определения определенных кодовых точек

unicode crossbones 0x2620
echo "$crossbones"

или сбросить первые 65536 кодов Unicode в stdout (на моем компьютере это занимает менее 2 с. Дополнительное пространство - для предотвращения попадания определенных символов друг в друга из-за моноширинного шрифта оболочки):

for a in {0..65535}; do unicodes "$a"; printf ' '; done

или рассказать немного типичную родительскую историю (для этого нужен Unicode 2010):

unicodes 0x1F6BC 32 43 32 0x1F62D 32 32 43 32 0x1F37C 32 61 32 0x263A 32 32 43 32 0x1F4A9 10

Объяснение:

  • printf '\UXXXXXXXX' печатает любой символ Unicode
  • printf '\\U%08x' number печатает printf '\\U%08x' number \UXXXXXXXX с числом, преобразованным в шестнадцатеричное, затем оно \UXXXXXXXX другому printf для фактической распечатки символа Unicode
  • printf распознает восьмеричные (0oct), шестнадцатеричные (0xHEX) и десятичные (0 или числа, начинающиеся с 1 до 9) числа, поэтому вы можете выбрать, какое из представлений подходит лучше всего.
  • printf -v var.. собирает выходные данные printf в переменную без разветвления (что значительно ускоряет процесс)
  • local variable существует, чтобы не загрязнять глобальное пространство имен
  • local -n var=other псевдонимы var к other, так что присваивание var изменяет other. Одна интересная часть здесь заключается в том, что var является частью локального пространства имен, а other - частью глобального пространства имен.
    • Обратите внимание, что в bash нет такой вещи, как local или global пространство имен. Переменные хранятся в среде, и такие всегда глобальные. Local просто убирает текущее значение и восстанавливает его, когда функция снова выходит из режима ожидания. Другие функции, вызываемые из функции local будут по-прежнему видеть "локальное" значение. Это принципиально иное понятие, чем все обычные правила области видимости, встречающиеся в других языках (и то, что делает bash, очень мощно, но может привести к ошибкам, если вы программист, который не знает об этом).

Ответ 15

Легко с одним вкладышем Python2/3:

$ python -c 'print u"\u2620"'    # python2
$ python3 -c 'print(u"\u2620")'  # python3

Результаты в:

Ответ 16

Если известно шестнадцатеричное значение символа юникода

H="2620"
printf "%b" "\u$H"

Если известно десятичное значение символа юникода

declare -i U=2*4096+6*256+2*16
printf -vH "%x" $U              # convert to hex
printf "%b" "\u$H"

Ответ 17

Вот список всех доступных смайликов Unicode:

https://en.wikipedia.org/wiki/Emoji#Unicode_blocks

Пример:

echo -e "\U1F304"
🌄

Для получения значения ASCII этого символа используйте hexdump

echo -e "🌄" | hexdump -C

00000000  f0 9f 8c 84 0a                                    |.....|
00000005

А затем используйте значения, сообщенные в шестнадцатеричном формате

echo -e "\xF0\x9F\x8C\x84\x0A"
🌄