使用 echo 时转义变量的问题

int*_*der 1 scripting bash

我正在尝试使用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? 
Run Code Online (Sandbox Code Playgroud)

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}"
Run Code Online (Sandbox Code Playgroud)

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."
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 9

echo的语法是从标准C逃逸不同通过作为支持printf/ awk/ $'...'...

在标准echo语法中,您需要0在八进制序列(可以有 1 到 3 位数字)的前面加一个前导符¹:

echo '\0360\0237\0246\0204'
Run Code Online (Sandbox Code Playgroud)

请注意,要使用bash'secho内置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"

Run Code Online (Sandbox Code Playgroud)

上面,只$UNICORN_utf8包含一个字符,用UTF8编码。其他包含反斜杠和数字的序列,旨在由相应的工具扩展。

该实用程序的%b格式printf也理解与echo. %b实际上是添加的,所以我们可以摆脱echo那些无法便携和可靠使用的东西

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

Run Code Online (Sandbox Code Playgroud)

另见(在zshbash³):

UNICORN_locale_encoding=$'\U1f984'
Run Code Online (Sandbox Code Playgroud)

这会为您提供一个以区域设置编码的独角兽,即使区域设置的编码不是 UTF-8 并且也具有该字符(可能只有 GB18030,其中编码为$'\225\60\330\66'以及$'\360\237\246\204'将是??( \N{CJK UNIFIED IDEOGRAPH-9983}\N{<private use area-E6E9>})的编码) .

一些printf实现(包括 GNUprintf和 的printf内置zshksh93以及bash(4.2 或更高版本)的最新版本)也在\UXXXXXXXX它们的格式参数(或%b除了 ksh93 的参数)中支持这些转义序列;GNU 需要 8 位数字。


¹GNU的coreutilsecho和busybox的echo支持\ooo-e作为扩展(未时POSIXLY_CORRECT是在用于GNU环境echo

² 其他选项是使用非标准-e选项,但是当posixxpg_echo选项都启用时它不会工作,就像bash在 UNIX 合规模式下一样。

³ ksh93 和 mksh 也支持该语法,但无论语言环境的编码如何,都以 UTF-8 编码;在当前 (2018) 版本的 FreeBSD 中sh,您需要\U0001f984并且它仅适用于 UTF-8 语言环境。