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

Я хотел бы добавить череп Unicode и скрещенные кости в приглашение моей оболочки (в частности, «SKULL AND CROSSBONES» (U + 2620)), но я не могу понять магическое заклинание, чтобы заставить эха плюнуть на него или любой другой, 4-значный символ Юникода. Двузначные легко. Например, echo -e “\ x55”,.

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

В приложении терминала MacOS Перейдите в раздел Настройки-> Кодировки и выберите Юникод (UTF-8).

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

 $ printf '\xE2\x98\xA0' ☠ 

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

 $ printf ☠ | hexdump 0000000 98e2 00a0 0000003 
 % echo -e '\u2620' # \u takes four hexadecimal digits ☠ % echo -e '\U0001f602' # \U takes eight hexadecimal digits 😂 

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

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

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

На терминале, на котором запущен 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

Вот полностью внутренняя реализация Bash, без разветвления, неограниченный размер символов Unicode.

 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 

Выход был:

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

Просто поставьте «☠» в свой сценарий оболочки. В правильной локали и на консоли с поддержкой Unicode он будет печатать только штрафом:

 $ echo ☠ ☠ $ 

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

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

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

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

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

U + 2620, кодированный как UTF-8, – E2 98 A0.

Итак, в Баше,

 export PS1="\342\230\240" 

сделают вашу оболочку подсказкой черепа и костей.

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

 $ echo -e '\u2620' ☠ 

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

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

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

Тест с Bash 4.2.37 (1):

 $ printf '\u2620\n' ☠ 

Любая из этих трех команд будет печатать символ, который вы хотите в консоли, если консоль принимает символы 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).

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

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

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

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

Основываясь на вопросах переполнения стека Unix, удалите первый токен и https://stackoverflow.com/a/15903654/781312 :

 (octal=$(echo -n ☠ | od -t o1 | head -1 | cut -d' ' -f2- | sed -e 's#\([0-9]\+\) *#\\0\1#g') echo Octal representation is following $octal echo -e "$octal") 

Вывод следующий.

 Octal representation is following \0342\0230\0240 ☠ 

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

 echo -e '\U1f602' 

Я хочу назначить его переменной, использующей синтаксис $ ‘…’

 x=$'\U1f602' echo $x 

Легко через Python:

 $ python -c 'print u"\u2620"' 

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

  

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

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

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

 unicode crossbones 0x2620 echo "$crossbones" 

или сбрасывать первые 65536 кодов unicode в stdout (занимает меньше двух секунд на моей машине. Дополнительное пространство – это предотrotation streamа отдельных символов друг в друга из-за monoширинного шрифта оболочки):

 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 печатает \UXXXXXXXX с числом, преобразованным в шестнадцатеричный, это затем подается на другой printf чтобы на самом деле распечатать символ Unicode
  • printf распознает восьмеричные (0oct), hex (0xHEX) и десятичные (0 или цифры, начинающиеся с 1 до 9) в качестве чисел, поэтому вы можете выбрать, какое представление лучше всего подходит
  • printf -v var .. собирает вывод printf в переменную, без fork (что значительно ускоряет работу)
  • local variable не должна загрязнять глобальное пространство имен
  • local -n var=other псевдонимы var to other , так что присвоение var изменяет other . Одна интересная часть здесь состоит в том, что var является частью локального пространства имен, а other является частью глобального пространства имен.
    • Обратите внимание, что в bash отсутствует local или global пространство имен. Переменные хранятся в среде, и они всегда являются глобальными. Local просто отбрасывает текущее значение и восстанавливает его, когда функция снова остается. Другие функции, вызванные внутри функции с local будут по-прежнему видеть «локальное» значение. Это принципиально другая концепция, чем все обычные правила определения области видимости на других языках (и то, что bash делает очень мощно, но может привести к ошибкам, если вы программист, который этого не знает).

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

 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" 
Давайте будем гением компьютера.