bash - 回显表情符号时如何在 bash shell 中移动光标?

标签 bash shell unicode emoji

我正在使用描述的光标移动功能为 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/

相关文章:

Unix 上的 C++ : Redirecting Shell Output

linux - 创建 bash 脚本以自动执行分析多个文件的任务

bash - 如何在 BASH 中使用 xmlstarlet 计算 XML 文档中的元素数量?

bash - 在unix中获取环境变量的值

linux - 查找命令 - 带 -exec 句柄的语法

linux - crontab 没有按计划时间运行

phpMyAdmin 不会在数据库中正确显示 Unicode (utf-8) 字符,但在 Web 中正确显示

java - JRE 错误? JTable 包含特定字符串 -> ArrayIndexOutOfBoundsException

python - 如何在 xpath 字符串中使用 unicode? (统一码编码错误)

java - 使用 find 将文件传递到 jar