Проблемы с экранированием переменной при использовании echo

Я пытаюсь избежать следующего кода с помощью команды echo но продолжаю получать реальный октет, а не эмодзи.

Также, где я могу найти октетные значения эмодзи? Кажется, я всегда нахожу значения UTF-8 .

 #!/usr/bin/env bash UNICORN='\360\237\246\204\n' FIRE='' # this does not work when I run the script printf '\360\237\246\204\n' printf "Riding a ${UNICORN:Q}" echo "Riding a ${UNICORN:Q}" #[Fails]: how to extract the actual emoji? 

EDIT_1: просто обновить код после прочтения комментариев

 #!/usr/bin/env bash # Note: use hexdump -b to get one-bye octal display UNICORN_UTF8=$'\360\237\246\204' printf "U1F525\n"|hexdump -b # [ASK]: How to translate the return value to a valid UTF8 ? FIRE_UTF8=$'\125\061\106\065\062\065\012' echo "Riding a ${UNICORN_locale_encoding}" echo "${UNICORN_UTF8} + ${FIRE_UTF8}" 

EDIT_2: публикация окончательного кода. Это вроде работает.

 #!/usr/bin/env bash # Author: # Usage: # Note: use hexdump -b to get one-bye octal display of the emoji (needed for when ≠ computers use ≠ commandLine tools) # Ex: printf "U1F525\n"|hexdump -v -e '"\\" 1/1 "%03o"' ; echo UNICORN_UTF8=$'\360\237\246\204' FIRE_UTF8=$'\xF0\x9F\x94\xA5' LEAVE_SPACE=\^[a-zA-Z0-9_]*$\ echo "Riding an ${UNICORN_UTF8} ${LEAVE_SPACE} out of a ${FIRE_UTF8} ${LEAVE_SPACE} house." 

Синтаксис echo отличается от стандартного C-escape, поддерживаемого printf / awk / $'...'

В стандартном синтаксисе echo вам нужно ввести 0 перед восьмеричной последовательностью (которая может иметь от 1 до 3 цифр) ¹:

 echo '\0360\0237\0246\0204' 

Обратите внимание, что для того, чтобы xpg_echo функция bash работала с этим, вам нужно включить xpg_echo xpg_echo²:

 $ UNICORN_utf8_printf_format='\360\237\246\204' $ UNICORN_utf8_echo='\0360\0237\0246\0204' $ UNICORN_utf8=$'\360\237\246\204' $ printf "$UNICORN_utf8_printf_format\n" 🦄 $ printf '%s\n' "$UNICORN_utf8" 🦄 $ shopt -s xpg_echo $ echo "$UNICORN_utf8_echo" 🦄 

Выше только $UNICORN_utf8 содержит символ,, закодированный в UTF8. Другие содержат последовательности обратной косой черты и цифр, которые должны быть расширены соответствующими инструментами.

Формат %b утилиты printf также понимает те же последовательности, что и echo . %b фактически было добавлено, поэтому мы можем избавиться от echo который невозможно использовать переносимо и надежно .

 $ printf '%b\n' "$UNICORN_utf8_echo" 🦄 

Смотрите также (в zsh и bash ³):

 UNICORN_locale_encoding=$'\U1f984' 

Это дает вам Unicorn, закодированный в кодировке локали, что позволит ему работать, даже если кодировка локали не UTF-8 и также имеет этот символ (вероятно, только GB18030, где 🦄 кодируется как $'\225\60\330\66' и где $'\360\237\246\204' будет кодировать 馃 ( \N{CJK UNIFIED IDEOGRAPH-9983}\N{} )).

Некоторые реализации printf (включая GNU printf и встроенную ksh93 printf zsh , ksh93 и последние версии bash (4.2 или выше)) также поддерживают эти escape-последовательности \UXXXXXXXX в своих аргументах формата (или аргументах %b за исключением ksh93); GNU нужно 8 цифр.


¹ GNU coreutils поддерживает echo и busybox echo \ooo с -e в качестве расширения (кроме случаев, когда POSIXLY_CORRECT находится в среде для GNU echo )

² другой вариант – использовать нестандартную опцию -e , но тогда она не будет работать, когда xpg_echo опции posix и xpg_echo , например, когда bash находится в режиме соответствия UNIX.

³ ksh93 и mksh также поддерживают этот синтаксис, но кодируют в UTF-8 независимо от кодировки локали; в текущих (2018) версиях FreeBSD sh вам нужен \U0001f984 и он работает только в локалях UTF-8.

 $ echo $'\360\237\230\200\012' 😀 

(это bash ‘s echo , GNU bash, версия 4.3.43 (1) -релиз (x86_64-redhat-linux-gnu))

Или вы можете использовать двоичный файл echo :

 $ /usr/bin/echo -e "\360\237\230\200\012" 😀 

Как я это получил? Я использовал ответ maulinglawns выше, чтобы увидеть восьмеричное смайлика:

 $ printf "\U1F600\n" 😀 $ printf "\U1F600\n"|hexdump -b 0000000 360 237 230 200 012 0000005 

hexdump :
-b, --one-byte-octal one-byte octal display

РЕДАКТИРОВАТЬ: Если вы хотели смайлик единорога:

 $ echo $'\360\237\246\204' 🦄 $ `which echo` -e '\360\237\246\204' 🦄 

Если вам нужен какой-то общий способ получения восьмеричного числа в этом формате:

 printf "\U1F600\n"|hexdump -v -e '"\\" 1/1 "%03o"' ; echo \360\237\230\200\012 

Выходные данные include \n как \012 . “; Echo” добавит новую строку в конце, это полезно при попытке выполнить ее в командной строке, иначе приглашение оболочки будет показано сразу после вывода.