Ответ 1
В UTF-8 это фактически 6 цифр (или 3 байта).
$ printf '\xE2\x98\xA0'
☠
Чтобы проверить, как это кодируется консолью, используйте hexdump:
$ printf ☠ | hexdump
0000000 98e2 00a0
0000003
Я хотел бы добавить череп и скрещенные кости Юникода в мою подсказку оболочки (в частности, "ЧЕРЕП И КРЕСТЫ" (U + 2620)), но я не могу понять магическое заклинание, которое заставило бы эхо выплюнуть его или любое другое, 4-значный Unicode символ. Двузначные легко. Например, echo -e "\ x55",.
В дополнение к ответам ниже следует отметить, что, очевидно, ваш терминал должен поддерживать Unicode, чтобы вывод был тем, что вы ожидаете. gnome-терминал хорошо справляется с этой задачей, но он не обязательно включен по умолчанию.
В приложении MacOS Terminal перейдите в Preferences-> Кодировки и выберите Unicode (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, а затем номер кодовой точки в виде 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
Здесь полная внутренняя реализация 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
Выход был:
─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
Просто вставьте "☠" в свой скрипт оболочки. В правильной локали и на консоли с поддержкой Unicode он будет печататься очень хорошо:
$ echo ☠
☠
$
Уродливым "обходным путем" может быть вывод последовательности UTF-8, но это также зависит от используемой кодировки:
$ echo -e '\xE2\x98\xA0'
☠
$
Быстрый однострочный перевод для преобразования символов UTF-8 в их 3-байтовый формат:
var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
Я использую это:
$ echo -e '\u2620'
☠
Это довольно просто, чем поиск в шестнадцатеричном представлении... Я использую это в своих скриптах оболочки. Это работает на gnome-term и urxvt AFAIK.
Вам может потребоваться кодировать кодовую точку как восьмеричную, чтобы быстрое расширение могло правильно декодировать ее.
U + 2620, кодированный как UTF-8, является E2 98 A0.
Итак, в Bash,
export PS1="\342\230\240"
сделает запрос оболочки черепом и костями.
Любая из этих трех команд будет печатать символ, который вы хотите в консоли, если консоль принимает 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).
Если вы хотите глубоко погрузиться в преобразование чисел в символы: посмотреть здесь!
В bash для вывода символа Unicode для вывода используйте \x,\u или\U (сначала для шестнадцатеричного шестнадцатеричного числа, второго для шестнадцатеричного шестнадцатеричного числа, третьего для любой длины)
echo -e '\U1f602'
Если вы хотите присвоить его переменной, используйте синтаксис $ '...'
x=$'\U1f602'
echo $x
Встроенный 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'
☠
Если вы не против однострочного Perl:
$ perl -CS -E 'say "\x{2620}"'
☠
-CS
позволяет декодировать UTF-8 на входе и кодировку UTF-8 на выходе. -E
оценивает следующий аргумент как Perl, с такими современными функциями, как say
. Если вы не хотите использовать новую строку в конце, используйте print
вместо say
.
Извините за возрождение этого старого вопроса. Но при использовании 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'
печатает любой символ Unicodeprintf '\\U%08x' number
печатает printf '\\U%08x' number
\UXXXXXXXX
с числом, преобразованным в шестнадцатеричное, затем оно \UXXXXXXXX
другому printf
для фактической распечатки символа Unicodeprintf
распознает восьмеричные (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
, очень мощно, но может привести к ошибкам, если вы программист, который не знает об этом).Основываясь на вопросах Unix cut, удалите первый токен и fooobar.com/questions/40855/...:
(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
☠
Легко с одним вкладышем Python2/3:
$ python -c 'print u"\u2620"' # python2
$ python3 -c 'print(u"\u2620")' # python3
Результаты в:
☠
Если известно шестнадцатеричное значение символа юникода
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"
Вот список всех доступных смайликов 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"
🌄