我如何计算各种字符的terminal列宽?

我正在计算各种打印和非打印ASCII / Unicode字符将在terminal视图中占用的terminal列数。

例如,水平制表符( \t )占用8列,颜色代码(即\x1b32m )占用0列,而固定大小的宽string(即,可能占用2列)。 当然在主要的ASCII集中有很多只占用1列(即aZ/0-9 ,标点符号等)。

我遇到了node.js模块, wcwidth ,这似乎有助于计算宽字符的string,但没有做我期望的其他字符,如颜色代码和标签。

例如:

 var wcwidth = require('wcwidth'); console.log("TAB WIDTH", wcwidth('\t')); console.log("한 WIDTH", wcwidth('한')); console.log("Color Code WIDTH", wcwidth('\x1b32m')); console.log("X WIDTH", wcwidth('X')); 

输出:

 TAB WIDTH 0 한 WIDTH 2 Color Code WIDTH 3 X WIDTH 1 

我似乎无法在任何地方find任何有关这方面的信息,但我想可以想象,在古代,人们必须解决这个问题。

如果可能有一种方法使用bash脚本,或任何库,应用程序或工具,我也完全开放。

任何帮助非常感谢! :) 谢谢

对于任何需要知道光标在屏幕上的程序,从ls表格输出到可编辑的命令行,再到全屏应用程序,这确实是一个问题。 正如您已经注意到的,它不能通过wcwidth或wcswidth来解决,wcwidth或wcswidth仅为可打印字符的(string)定义。 (即使对于许多字符也没有很好的定义 )。而且,控制序列不仅可以改变颜色,还可以改变光标的位置,甚至支持字体大小的效果。

相反,terminal控制库,如ncurses [ npmsearch ]有时使用。 这些似乎并没有告诉你string的宽度,但是由于它们分别跟踪文本属性(如颜色),并自己生成控制序列来定位和设置文本,所以它们可以帮助将事物放置在给定位置的屏幕上。

不幸的是,我不认为除此之外还有很多可用的东西,应用程序要么忽略复杂性,要​​么以特殊的方式处理它们。


清除一个常见的误解:水平制表符(HT, \t )没有这样的宽度; 它是一种“格式化效果”,如回车或换页,按照一定的规则重新定位光标。

HT(水平制表):一种格式执行器,用于控制打印位置沿打印行的一系列预定位置的移动。 (也适用于显示设备和穿孔卡上的跳过function。)

– 美国信息交换标准代码[ASCII],1968年,转载于RFC 20

最常见的实现是每八个列都有固定的制表位

  1 2 1.......9.......7.......5..... 1\tXYZ 1 XYZ 12\tXYZ 12 XYZ 1234567\tXYZ 1234567 XYZ 12345678\tXYZ 12345678 XYZ 123456789\tXYZ 123456789 XYZ 

尽pipe一些系统支持控制序列或其他方式来设置制表位在任意距离处的位置,如一些文字处理器中的标尺栏。

一个标签不占用8列。 它输出一个空格,然后有足够的空格,以确保下一个字符将被输出到索引为0 mod 8的下一列(或者如果从1开始计数,则为1 mod 8)。换句话说,你不能说出有多宽除非你知道你在哪里。

颜色代码( \x1b[32m )可能占用零空间,但也可能不占用空间; 这取决于控制台的terminal仿真器的性质。 大多数terminal仿真器将识别CSI[Pm代码,但还有其他代码更具特色。 例如,

 printf $'\x1b]2;A window\x1b\\' 

将在xterm设置窗口标题,因此不会产生输出。 但是在Linux控制台中,文本将会显示;A window ,占用9个字符。

总而言之,问题不是那么容易,只能用很多背景来回答,因为没有绝对的答案。