我想在 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
包括 GNUprintf
和printf
内置的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
起源地,bash
FreeBSD ksh93
)也在其引用中支持该表示法。mksh
sh
\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