使用 ANSI 框字符在终端中绘制表格

问题描述 投票:0回答:3

我正在尝试打印一个比纯文本表示更赏心悦目的表格。基本上我想转换这样的东西:

+-----+--------+
| age | weight |
+-----+--------+
| 10  | 100    |
| 80  | 500    |
+-----+--------+

像这样:

┌─────┬────────┐
| age | weight |
├─────┼────────┤
│ 10  │   100  │
│ 80  │  500   │
└─────┴────────┘

这是我在终端中看到的屏幕截图:

in terminal looks like this

注意行之间的间隙。我的问题是它们没有正确连接,而其他使用 ANSI 打印的 Unix 工具在终端中看起来很好。例如,树,如果我在终端中运行

tree -A
`我得到这个:

tree in terminal

注意垂直线是如何连接在一起的。这很有趣,因为当我将树的输出复制并粘贴到文本编辑器并运行我的脚本时,我得到如下内容:

tree in my code

显然我错过了一些关于在终端中打印 ANSI 字符的信息,并且无法通过谷歌搜索找到任何有关它的信息。谁能解释一下这个话题?

unix terminal tabular
3个回答
29
投票

我想我应该回答我自己的问题。经过一番研究以及朋友和老板 Linus 的帮助后,我发现我需要强制终端首先进入图形模式,然后打印特殊字符,然后返回到文本模式。切换到图形模式的ascii代码是14,15将返回文本模式。这是 ruby 中的代码:

printf("%c\n", 14)
printf("%c ", 0x6A) # ┘
printf("%c ", 0x6B) # ┐
printf("%c ", 0x6C) # ┌
printf("%c ", 0x6D) # └
printf("%c ", 0x6E) # ┼ 
printf("%c ", 0x71) # ─
printf("%c ", 0x74) # ├
printf("%c ", 0x75) # ┤
printf("%c ", 0x76) # ┴
printf("%c ", 0x77) # ┬
printf("%c\n", 0x78) # │


a = sprintf("%c", 0x6C) + # ┌
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c\n", 0x6B) +  # ┐
sprintf("%c", 0x78) + # │
#print("      ")
"      " + 
sprintf("%c\n", 0x78) + # │
sprintf("%c", 0x6D) + # └
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x71) + # ─
sprintf("%c", 0x6A)  # ┘

puts a

printf("%c\n", 15)

3
投票

您确实应该研究 ncurses 及其变体。尽管它最初是为 C 语言编写的,但有一系列不同的语言绑定。它提供了一套相当丰富的库,用于生成带有窗口、菜单、盒装边框等的 TUI(文本 UI)。 首先访问维基百科来查找其他一些参考资料。


0
投票

首先感谢 Allen Bargi 提出这个问题并提供他的 ruby 解决方案。这帮助我为 bash 编写了一个解决方案,因此不依赖 ruby。

首先我们可以打印出画线字符列表来演示它是如何工作的:

printf "\e(0"  ; # Begin Graphics
printf "\x6A " ; # ┘
printf "\x6B " ; # ┐
printf "\x6C " ; # ┌
printf "\x6D " ; # └
printf "\x6E " ; # ┼
printf "\x71 " ; # ─
printf "\x74 " ; # ├
printf "\x75 " ; # ┤
printf "\x76 " ; # ┴
printf "\x77 " ; # ┬
printf "\x78 " ; # │
printf "\e(B"  ; # End Graphics
printf "\n";

输出如下所示:

┘ ┐ ┌ └ ┼ ─ ├ ┤ ┴ ┬ │ 

现在我可以打印问题中格式的示例表

# Header Top
printf "\e(0" ; # Begin Graphics
printf "\x6C" ; # ┌
printf "%.0s\x71" {1..5} ; # ─ x5
printf "\x77" ; # ┬
printf "%.0s\x71" {1..8} ; # ─ x8
printf "\x6B" ; # ┐
printf "\n";
# Column Names
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " age "
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " weight "
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\n";
# Header Bottom
printf "\x74" ; # ├
printf "%.0s\x71" {1..5} ; # ─ x5
printf "\x6E" ; # ┼
printf "%.0s\x71" {1..8} ; # ─ x8
printf "\x75" ; # ┤
printf "\n";

# Data Row. Be careful to print the data normally
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " %3s " 10
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " %6s " 100
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\n";

# Data Row. Be careful to print the data normally
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " %3s " 80
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\e(B" ; # End Graphics
printf " %6s " 500
printf "\e(0" ; # Begin Graphics
printf "\x78" ; # │
printf "\n";

# Finally the Table Bottom
printf "\x6D" ; # └
printf "%.0s\x71" {1..5} ; # ─ x5
printf "\x76" ; # ┴
printf "%.0s\x71" {1..8} ; # ─ x8
printf "\x6A" ; # ┘
printf "\n";
printf "\e(B" ; # End Graphics

这是结果(Stack Overflow 显示它,行之间有间隙,但在我的各种终端上我没有看到任何间隙):

┌─────┬────────┐
│ age │ weight │
├─────┼────────┤
│  10 │    100 │
│  80 │    500 │
└─────┴────────┘

如果你想使用Python,那么

\e
可以替换为
\x1B

print("\x1B(0", end='')  # Begin Graphics
print("\x1B(B", end='')  # End Graphics
print("\x6A", end='')    # ┘
# etc...

我还尝试看看是否有一种很好的方法将其与 util-linux 命令集成

column
,但不幸的是,这不会填充表格的最后一列,除非您将其右对齐。一个模式是始终在每一行前面加上一个虚拟的单空格列:

$ sep=`printf "\e(0\x78\e(B"`
$ printf "Age,Weight\n10,100\n80,500\n" | sed -e 's/^/ ,/' -e 's/$/, /' | column -t -s ',' -o " $sep " 
  │ Age │ Weight │  
  │ 10  │ 100    │  
  │ 80  │ 500    │  
© www.soinside.com 2019 - 2024. All rights reserved.