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



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



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



в приложении терминала macOS перейдите в Настройки - > кодировки и выберите Unicode (UTF-8).

686   16  

16 ответов:

в 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 или новее.

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

например,ВИМ текстовый редактор вы бы войти в режим вставки и нажмите Ctrl + V + U и затем номер кодовой точки в виде 4-значного шестнадцатеричного числа (pad с нулями, если это необходимо). Так что вы бы набрали Ctrl + V + U2 620. Смотрите:какой самый простой способ вставить символы Юникода в документ?

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

echoCTRL+SHIFT+ U2620введитевведите

(первый ввод завершает ввод Юникода, а второй запускает

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

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

function unichr {
    local c=    # 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.

Так в bash,

export PS1="200"

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

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

$ echo -e '\u2620'
☠

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

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

   \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 включен) текстовый редактор.

Если вам нужно увидеть, как такая кодовая точка Unicode кодируется в 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

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

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

если вы не возражаете против Perl one-liner:

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

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

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

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

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

Octal representation is following 423040
☠

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

echo -e '\U1f602'

Я вы хотите назначить его переменной use $'... синтаксис

x=$'\U1f602'
echo $x

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

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

результаты:

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

unicode() { local -n a=""; local c; printf -vc '\U%08x' ""; 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 печать \UXXXXXXXX с числом, преобразованным в Hex, это затем подается на другой printf на самом деле распечатать символов Unicode
  • printf распознает восьмеричные (0oct), шестнадцатеричные (0xHEX) и десятичные (0 или числа, начинающиеся с От 1 до 9) в виде чисел, так что вы можете выбрать, какое представление подходит лучше всего
  • printf -v var .. собирает выходные данные printf в переменную, без вилки (что чрезвычайно ускоряет процесс)
  • local variable есть ли, чтобы не загрязнять глобальное пространство имен
  • local -n var=other псевдонимы var до other, такие, что задание var изменяет other. Одна интересная часть вот, что var входит в локальное пространство имен, в то время как other является частью глобального пространства имен.
    • Пожалуйста, обратите внимание, что нет такой вещи, как local или global пространства bash. Переменные хранятся в среде, и они всегда являются глобальными. 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"

Comments

    Ничего не найдено.