在我在网上或各种代码中看到的人们的 ' .*rc
' 文件中,我倾向于看到很多人手动使用 ANSI 转义序列而不是使用tput
.
我的理解tput
更通用/安全,所以这让我想知道:
是否有任何客观原因应该使用转义序列代替tput
? (可移植性、错误鲁棒性、异常终端......?)
答案1
tput
可以处理典型 shell 脚本编写者认为不太可用的表达式(例如 insgr
和)。setaf
要了解所涉及的内容,请查看应用(格式化)选项infocmp
的输出。-f
这是使用 xterm 中的这些字符串的示例之一术语信息描述:
xterm-16color|xterm with 16 colors,
colors#16,
pairs#256,
setab=\E[
%?
%p1%{8}%<
%t%p1%{40}%+
%e
%p1%{92}%+
%;%dm,
setaf=\E[
%?
%p1%{8}%<
%t%p1%{30}%+
%e
%p1%{82}%+
%;%dm,
setb=
%p1%{8}%/%{6}%*%{4}%+\E[%d%p1%{8}%m%Pa
%?%ga%{1}%=
%t4
%e%ga%{3}%=
%t6
%e%ga%{4}%=
%t1
%e%ga%{6}%=
%t3
%e%ga%d
%;
m,
setf=
%p1%{8}%/%{6}%*%{3}%+\E[%d%p1%{8}%m%Pa
%?%ga%{1}%=
%t4
%e%ga%{3}%=
%t6
%e%ga%{4}%=
%t1
%e%ga%{6}%=
%t3
%e%ga%d
%;
m,
use=xterm+256color,
use=xterm-new,
格式将事情分开——执行相同操作的脚本或程序必须遵循这些曲折。大多数人放弃并只使用最简单的字符串。
16 色功能借用自 IBM aixterm,它将前景和背景各 16 个代码映射到两个范围;
- 前景到 30-37 和 90-97
- 背景介绍 40-47 和 100-107
一个简单的脚本
#!/bin/sh
TERM=xterm-16color
export TERM
printf ' %12s %12s\n' Foreground Background
for n in $(seq 0 15)
do
F=$(tput setaf $n | cat -v)
B=$(tput setab $n | cat -v)
printf '%2d %12s %12s\n' $n "$F" "$B"
done
和输出显示它是如何工作的:
Foreground Background
0 ^[[30m ^[[40m
1 ^[[31m ^[[41m
2 ^[[32m ^[[42m
3 ^[[33m ^[[43m
4 ^[[34m ^[[44m
5 ^[[35m ^[[45m
6 ^[[36m ^[[46m
7 ^[[37m ^[[47m
8 ^[[90m ^[[100m
9 ^[[91m ^[[101m
10 ^[[92m ^[[102m
11 ^[[93m ^[[103m
12 ^[[94m ^[[104m
13 ^[[95m ^[[105m
14 ^[[96m ^[[106m
15 ^[[97m ^[[107m
这些数字被分开,因为 aixterm 使用 30-37 和 40-47 范围来匹配 ECMA-48(也称为“ANSI”)颜色,并使用 90-107 范围作为代码不是标准中定义。
这是 xterm 使用的屏幕截图TERM=xterm-16color
,您可以在其中看到效果。
进一步阅读:
infocmp
-比较或打印 terminfo 描述- 参数化字符串, 在里面术语信息手动的。
tput
,reset
- 初始化终端或查询 terminfo 数据库- ECMA-48:编码字符集的控制函数
aixterm
命令- 鲜艳的颜色不就等于大胆吗?(XTerm 常见问题解答)
答案2
在 UNIX 平台可以连接各种设备的时代,我仍然更喜欢 tput 及其朋友而不是字面的转义序列。
我认为真正的原因是大多数人根本不了解tput
及其相关的terminfo
/termcap
文件和库。
答案3
的优点tput
是它会查找终端可以做什么以及如何做,这使得它能够为您的终端获取正确的信息。其缺点tput
是它会查找终端可以做什么以及如何做,这可能会导致它为您的终端获取不正确的信息。
tput
在中查找信息术语信息数据库,或在较旧的系统上术语帽数据库。通常的工作方式是,系统TERM
在终端启动时将环境变量设置为终端名称。对于物理终端,这就是getty
。对于终端仿真器,这是终端仿真器程序的工作。在终端中运行的程序(包括)在 termcap 或 terminfo 数据库中tput
查找 的值,这两个数据库都将终端名称映射到“功能”。TERM
终端功能表明终端可以做什么以及如何做:是否可以自动换行、有多少列、按键Left发送什么字符序列、向终端发送什么字符序列以将光标向左移动等。
这一切都很棒,因为它允许程序和终端独立工作。系统只需维护一个包含每种可用终端类型的功能的文件。对于物理终端,该文件基本上是终端的驱动程序。对于终端仿真器,该文件应与终端仿真器程序一起分发。 (每种终端类型不一定有一个文件,但这只是一个与此处无关的实现细节。)
当您考虑远程登录时,这就不行了。诸如rlogin
和 之类的程序ssh
是服务器上的终端仿真器,但它们所做的只是中继到客户端的“真实”终端。所以它们没有自己的终端类型,它们只是传输TERM
环境变量,以便在终端中运行的远程程序知道该终端的功能。但是,服务器上运行的程序随后会在服务器的 termcap/terminfo 数据库中查找终端名称,该数据库可能不知道客户端上可用的终端类型。
在 20 世纪 70 年代,美国国家标准协会标准化了一组能力,最终被几乎所有物理终端所遵循。终端仿真器继续遵循此标准。当所有终端都具有相同的功能时,终端数据库并没有真正的用处。因此人们养成了对终端转义序列进行硬编码的习惯,要么是因为他们不了解终端数据库,要么只是因为它更容易:您只需查阅终端的文档或实验即可,无需学习termcap/terminfo 接口。
此外,在远程登录通常是由同一人员管理的同一站点上的另一台计算机的日子里,确保所有系统都知道所有其他系统的终端并不困难。但在互联网上,这无法扩展。如今,几乎所有图形终端模拟器都设置TERM
为xterm
,因为这是一个您确信到处都知道的终端名称。有些设置TERM
为xterm-256color
,这可能会给您在某些不知道该名称的系统上带来麻烦。
设置为广泛支持的值而不是准确描述终端功能的值的问题TERM
是,您最终会错过旧版本的 xterm 中不存在的功能。例如,古代的xterm只支持8种颜色,所以在很多系统上,termcap/terminfo数据库条目xterm
说颜色的数量是8。那么如何使用其他颜色呢?您可以定义一个新的终端名称,例如xterm-256color
,现在许多系统都这样做,但不是全部。而且它甚至不准确:现代 xterm 支持 24 位颜色。因此,如果您想要 256 色,tput
可能会给您带来远程登录的麻烦(假设您的系统上确实有xterm-256color
),而如果您想使用 24 位颜色,tput
则不会有帮助。
总之,tput
它为您提供了在不常见终端上的可移植性,但牺牲了功能。直接使用转义序列可以让您可移植到实际使用的终端,而不受功能限制。
答案4
原因之一是它tput
是外部命令,因此可能比内置 shell 转义码运行得慢。另一件事是,人们可以轻松地创建一个将 ANSI 转义代码与 shell 特定转义字符相结合的衬里,例如在bash
提示符中:
PS1='\[\033[1;32m\]\u@\h\[\033[1;34m\] \w >\[\033[0m\] '
同样在zsh
:
PS1=$'%{\e[1;32m%}%n@%m%{\e[1;34m%} %3~> %{\e[0m%}'
这里一切都清晰而紧凑。如果tput
需要将其拆分为多行,或者使其变得更长、更复杂,执行tput
多次等。