it-swarm.com.ru

Как вы повторяете 4-значный символ Unicode в Bash?

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

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

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

188
masukomi

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

$ printf '\xE2\x98\xA0'
☠

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

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

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

78
Juliano

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

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

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

echoCTRL+SHIFT+U262ENTERENTER

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

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

66
RobM

Вот полностью внутренняя реализация 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

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

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

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

$ echo ☠
☠
$

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

$ echo -e '\xE2\x98\xA0'
☠
$
13
Joachim Sauer

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

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

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

$ echo -e '\u2620'
☠

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

8
Metal3d

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

U + 2620 в кодировке UTF-8 - это E2 98 A0.

Так что в Баш,

export PS1="\342\230\240"

превратит вашу ракушку в череп и кости.

7
cms

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

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

4
user2350426

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

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

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

3
Flimm

Встроенная функция 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'
☠
3
Michael Jaros

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

echo -e '\U1f602'

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

x=$'\U1f602'
echo $x
3
user2622016

На основе вопросов переполнения стека Unix cut, удалите первый токен и 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
☠
2
test30

Извините за возрождение этого старого вопроса. Но при использовании 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 с. Дополнительное пространство - для предотвращения попадания определенных символов друг в друга из-за моноширинного шрифта Shell):

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), шестнадцатеричные (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, очень мощно, но может привести к ошибкам, если вы программист, который не знает об этом).
2
Tino

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

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

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

2
Chris Johnson

Вот список всех доступных смайликов 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"
????
0
Matheus Baldasso

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

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"
0
philcolbourn