如何删除终端中的unicode符号?

如何删除终端中的unicode符号?

有些符号占用两个字符单元。考虑这个脚本:

#!/usr/bin/env bash
echo '银^Htest'
echo 'а^Htest'

输出:

 test
test

我如何知道全角符号的代码点?某种正则表达式?如何计算一个字符串占用了多少个字符单元?如何删除输出的所有内容?

如果这很重要的话我正在使用xterm

UPD为了给你更大的画面,我试图显示进度,输出一些信息,擦除它,再次输出......为此,我将光标移动到行的开头(\r),擦除带有空格的行(tput cols) ,然后再次移动光标 ( \r)。但事实证明,该输出可能跨越几行。所以我决定计算字符数,向后移动(^H),擦除(输出与字符串长度一样多的空格),然后再次向后移动(^H)。

答案1

这实际上是四个问题:

  1. 我如何知道它们的代码点?
  2. 某种正则表达式?
  3. 如何计算一个字符串占用了多少个字符单元?
  4. 如何删除输出的所有内容?

OP 提到了 xterm,但只有最后两个可能特定于 xterm。

对于(1)和(2),echo命令没有太大帮助。你最好使用printf,它识别反斜杠转义。在一些实现中(例如,GNU 核心工具),包括 Unicode 常量,例如,

printf '\u94f6\btest'

虽然为了常用表达,您最好还是使用 Perl(可以处理 UTF-8)等脚本语言。

进一步阅读:

问题(3)和(4)更有趣。首先,脚本无法真正提前知道字符串需要多少个字符单元,而只能在事后测量它。这是因为宽度是基于终端和内核行为的组合。

  • xterm 使用宽度来决定字符应该有多宽,其中存在一些有关“宽”(双宽)字体的问题,并且 wcwidth 的实现反映了开发人员对模糊宽度 Unicode 值的偏见。 xterm 可以配置(在运行时)使用 Markus Kuhn 的副本实施wcwidth;请注意,它可能不完整也不匹配实际的系统区域设置信息。
  • 当 xterm 被告知擦除双角字符的一部分(如给定的示例中)时,它会用空格替换另一部分。大多数其他模仿 xterm 的终端都会这样做(尽管在快速检查中,我注意到一个终端只是简单地移动光标,导致宽字符和 ASCII 文本重叠)。如果你知道该值是双倍宽度,您可以简单地调整光标所在位置的概念。
  • Linux 内核对wcwidth.自那时以来基于Linux的系统2004年有一个功能stty叫做iutf8

它告诉内核输入是用 UTF-8 编码的,以便在规范输入模式下提供正确的编辑支持

  • Linux 内核功能对于编辑很有用输入,因为当退格键删除前一个字符时,它可以帮助终端驱动程序执行一些合理的操作。然而,没有可比的功能输出

,按照建议,使用光标位置报告(转义序列)来查找光标在不同点的位置。但如果你打算用它来决定如何清理线路,那么似乎更直接移动到打印 Unicode 值之前的位置,并从该点开始清除。

或者,您可以告诉终端在打印宽字符之前保存光标位置,然后恢复它(向后移动)。这可能看起来更干净、更可预测。恢复光标位置后,即可清除该行。所有这三个都可以使用转义序列来完成 - 或者tput:

tput sc
printf '\u94f6'
tput rc
tput el
printf 'test'

除了作为演示之外,这确实有一个缺点,即终端只有一个保存的光标位置,并且为了确保清除单/双宽字符,它会清除整行。但光标最终会到达“正确”的位置。

相关内容