我正在使用描述的光标移动功能为 Bash 编写游戏引擎 here .但是,如果我回显表情符号或其他超过 1 个字节的 UTF-8 字符,光标位置似乎会变得困惑。
例如,下面的代码应该回显“1🔈3”,将光标向后移动 3 个位置,然后在同一位置回显“abc”。结果应该仅为“abc”(理想情况下)。相反,我看到“1abc”
~ $ echo -e "1🔈3\033[3Dabc"
1abc
类似的问题可以用回车进给来说明:
~ $ echo -e "1🔈3\rabc"
abc3
请问有什么好的解决办法吗?我在 macOS 上使用终端应用程序。是否有任何可移植的方法来执行此操作?
注意:请注意,并非所有 UTF-8 字符似乎都以这种方式运行。大多数情况下,我只能用表情符号重现这个问题:
~ $ while true; do read -p "Enter emoji: " x; echo $x | hexdump; echo -e "1${x}3\033[3Dabc"; done
Enter emoji: 🔈
0000000 f0 9f 94 88 0a
0000005
1abc
Enter emoji: ♞
0000000 e2 99 9e 0a
0000004
abc
Enter emoji: ☞
0000000 e2 98 9e 0a
0000004
abc
Enter emoji: 😋
0000000 f0 9f 98 8b 0a
0000005
1abc
Enter emoji: 🃘
0000000 f0 9f 83 98 0a
0000005
abc
Enter emoji: 🀖
0000000 f0 9f 80 96 0a
0000005
abc
Enter emoji: 𝕭
0000000 f0 9d 95 ad 0a
0000005
abc
Enter emoji: 🇺🇸
0000000 f0 9f 87 ba f0 9f 87 b8 0a
0000009
1abc
Enter emoji: ✎
0000000 e2 9c 8e 0a
0000004
abc
最佳答案
问题的发生是因为 😋实际上是跨两列呈现的。在我的系统上,四个表情符号和八个数字一样长:
😋😋😋😋
12345678
预计单个宽字符将需要两个窄字符来覆盖它。
Unicode TR51-16 建议将这些表情符号视为宽:
Current practice is for emoji to have a square aspect ratio, deriving from their origin in Japanese. For interoperability, it is recommended that this practice be continued with current and future emoji. They will typically have about the same vertical placement and advance width as CJK ideographs.
根据建议,我可以轻松地将“表情符号”Unicode block 中的任何内容硬编码为宽。您的其他有效符号,例如 🀖 和 ☞ 不在表情 block 中(它们分别在麻将和杂项符号中)。
如果你想在运行时确定宽度,你可以,例如问 Python,尽管 Unicode 表本身将其标记为中性,但它有助于将其东亚宽度报告为全/宽:
$ python3 -c 'import sys; import unicodedata as u; print(u.east_asian_width(sys.argv[1]))' 😋
W
$ python3 -c 'import sys; import unicodedata as u; print(u.east_asian_width(sys.argv[1]))' ♞
N
🇺🇸 有点特殊,因为它由两个不同的区域指示符号和单独的代码点组成,但 Python 将它们中的每一个标记为中性,因此如果您将其视为 1,它仍然会加起来为 2。
关于bash - 回显表情符号时如何在 bash shell 中移动光标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56798307/