如何使用 bash 命令在终端上打印 UTF-8 符号。
这有效
echo -e '\U2586'
但以下是失败的
printf '%s\n' $(tput setaf 118) "\\u2586" $(tput sgr0)
答案1
在bash中,如果你想printf
在格式字符串后面的参数中扩展反斜杠转义序列,你应该使用%b
而不是%s
在格式字符串中:
printf '%b\n' "$(tput setaf 118)" "\u2586" "$(tput sgr0)"
既然你有三个论点,也许这可能更合适:
printf '%s%b%s\n' "$(tput setaf 118)" "\u2586" "$(tput sgr0)"
作为斯蒂芬·查泽拉斯指出,这将输出当前语言环境字符集中 U+2586 字符的编码。如果是 UTF-8,则结果将是 UTF-8;其他字符集会有所不同。如果字符集无法表示 U+2586,则结果将是字符串“\u2586”(zsh 将失败并出现“字符不在范围内”错误)。
这会在大多数情况下产生您想要的行为:如果可能,它会显示“▆”。如果你真的想要输出字符的 UTF-8 表示形式,在所有情况下,您可以通过覆盖区域设置来强制执行此操作,例如
LC_ALL= LC_CTYPE=en_US.UTF-8 printf '%s%b%s\n' "$(tput setaf 118)" "\u2586" "$(tput sgr0)"
(看LANG=C 和 LC_ALL=C 有什么区别?有关上面使用的变量设置的说明。)
答案2
\uxxxx
请注意,对和 的支持\UXXXXXXXX
首次添加到printf
2000 年独立实用程序的 GNU 实现中,但与其他转义序列一样,它们仅在格式参数或说明%b
符的参数中被识别。不用于%s
逐字显示字符串。
它们后来被添加到2003 年printf
的内置函数zsh
中(也适用于echo
/print
和$'...'
There),2004 年的 ksh93,2010 年的 bash (4.2) 以及此后可能还添加了一些内置函数。
但这不是标准的。有计划POSIX 指定$'...'
ksh93 的引号形式并且它们允许\u
/\U
序列,但目前的阻塞点之一是如果在解析和/或运行使用这些引号的命令时当前语言环境中的字符集不是 UTF-8,如何处理扩展。
尽管如此,如果您的脚本是在字符集为 UTF-8 的语言环境中启动的,并且此后您没有更改语言环境( 、LC_CTYPE
和LC_ALL
变量LANG
),则使用$'\uxxxx'
可能是获取基于字符的 UTF-8 编码的最可移植的方法在其 Unicode 代码点上。
用于$'\UXXXXXXXX'
代码点高于 0xFFFF 的字符。请注意,有些 shell 确实要求 的所有 4 位数字\u
和 的所有 8 位数字\U
。因此,为了获得最大的可移植性,例如,使用或$'St\u00E9phane'
。在任何 shell 中,您都需要 ,因为是十六进制数字,所以会被视为。对于支持的 shell ,您还可以使用或和 混合搭配引号运算符。$'St\U000000E9phane'
Stéphane
St\u00E9fan
Stéfan
$'St\ue9fan
St
\U0E9F
ane
f
$'\ue9'
$'St\ue9'$'fan'
St$'\ue9'fan
然后您可以将这些扩展传递给任何命令printf
或其他命令。
在您的特定情况下,您可以使用zsh
'sprint
内置函数:
print -P '%F{118}\u2586%f'
其中-P
启用提示扩展,无需运行命令即可设置前景色tput
。或者:
print -rP '%F{118}'$'\u2586''%f'
where禁用转义序列并使用引号的形式-r
按字面传递 U+2586 字符。print
$'...'
或者:
arbitrary_text=$'\u2586'' arbitrary text with \backslash and % characters'
print -r -- ${(%):-%F{118}}$arbitrary_text${(%):-%f}
其中print
不进行任何扩展,但颜色转义序列由%
参数扩展标志生成,并且 U+2586 逐字存储在变量中。打印-r