在 shell 脚本中打印复选标记/十字标记

在 shell 脚本中打印复选标记/十字标记

我想在 shell 脚本中打印复选标记和十字标记:

#!/bin/bash

echo -e "\xE2\x9C\x94 existing"
echo -e "\xE2\x9D\x8C missing"

为什么这不起作用?

答案1

正如OP在评论中透露的那样,他们正在使用sh file.sh.根据符号/bin/sh链接到的默认 shell,它可能不支持 unicode 字符。

例如,在 Ubuntu 上,默认 shell 是dash

$ dash
$ printf "\xE2\x9C\x94 missing\n"
\xE2\x9C\x94 missing
$ echo -e "\xE2\x9C\x94"
-e \xE2\x9C\x94

当您在交互式 shell 中调用命令时它起作用的原因是因为默认情况下用户交互式 shell(在 Ubuntu 上)/bin/bash

要正确运行脚本,您需要:

  • 运行它作为./file.sh
  • 将其作为正确 shell 的参数运行bash file.sh

或者,可以采用独立于 shell 的方法:

# this printf is standalone program, not shell built-in
$ /usr/bin/printf "\xE2\x9C\x94 check mark\n"
✔ check mark

$ python -c 'print "\xE2\x9C\x94 check mark"'
✔ check mark

$ perl -e 'print "\xE2\x9C\x94 check mark"'                                                                              
✔ check mark

答案2

请注意,这\xE2\x9C\x94是 U+2714 的 UTF-8 编码(重复选标记) 特点。

如果终端的字符集是 UTF-8(并且使用具有该字符的字体),这 3 个字节只会显示为复选标记。

对于终端仿真器,它们使用的字符集通常是它们启动时区域设置中的字符集。除非您更改了在该终端中启动的 shell 中的区域设置,否则您可以知道它是使用哪一个:

locale charmap

printf包括 GNUprintfprintf内置的zsh,bash以及(至少在基于 Debian 的系统上lksh的 POSIX 兼容变体)在内的多种实现支持:mksh

$ printf '\u2714\u274c\n'
✔❌

以区域设置的字符集的正确编码打印这些字符(ksh93 的printf内置也支持该\uXXXX表示法,但无论区域设置的字符集如何,始终以 UTF-8 输出)。printf内置支持它并且具有echo扩展转义序列(可能带有)的 shell-e通常也支持\uXXXX那里。

现在,AFAICT,这两个 U+274C 和 U+2714 字符在典型 GNU 系统上可用的唯一两个字符集是 UTF-8 和 GB18030。在使用不同字符集的区域设置中,printf将无法显示这些字符,因为它们根本不存在。根据实现情况,printf将按\u274C字面打印或因错误而失败。

一些 shell(它的zsh起源地,bashFreeBSD ksh93)也在其引用中支持该表示法。mkshsh\uXXXX$'...'

所以你可以这样做:

echo $'\u2714\u274c'

bash根据 shell,这些将扩展到解析命令时 ( ) 或运行命令时 ( zsh) 或始终采用 UTF-8 (ksh)时有效的语言环境编码。

POSIXly(在类 Unix 系统中可移植),如果您想打印任意字节序列,您将需要使用printf和 八进制表示法。

\xE2\x9C\x94(U+2714 的 UTF-8 编码)将可移植地打印在一行上:

printf '\342\234\224\n'

如果您希望将其转换为区域设置的正确编码,那就是:

printf '\342\234\224\n' | iconv -f UTF-8

POSIX 没有指定系统支持哪种字符编码,也没有指定其名称,但上述命令通常适用于支持 UTF-8 编码的 POSIX 系统。

答案3

使用原始的“剪切和粘贴”Unicode,我们得到了一个更具可读性的解决方案:

$ echo -e '☑ done\n☒ fail\n☐ to do'
☑ done
☒ fail
☐ to do

相关内容