第十三章 定制提示符
第十三章 定制提示符
前言
- 本章将会讲解一个看似微不足道的细节:shell 提示符。通过讲解,我们会发现 shell 和终端仿真器程序的内部工作机制。
- 和 Linux 中的很多程序一样,shell 提示符的可配置性很高。尽管大多数用户并不重视提示符,但是,一旦我们学会了怎样控制它,它就会成为一种相当有用的设备。
提示符的分解
- 基本介绍
- 系统的默认提示符看起来如下所示。
1
[me@linux ~]$
- 提示符是由名为 PS1 (prompt string 1 的缩写,即提示符字符串 1) 的环境变量定义的。
- echo 命令可以帮助用户看到 PS1 的值。
1
2[me@linuxbox ~]$ echo $PS1
[\u@\h \w]\$ - 如果输出的结果同本书的范例不同,也不需要担心。每一个 Linux 发行版本对此提示符字符串的定义都会有所不同,有一些甚至定义的很奇怪。
- PS1 包含了一些提示符中出现的符号,比如方括号、@ 符号和美元符号,但是其余的部分则令人困惑。
- shell 提示符中使用的转义字符
转义字符 | 含义 |
---|---|
\a | ASCII 铃声。在遇到该转义字符时,计算机发出哔哔声 |
\d | 当前日期,以星期、月、日的形式表示,如 Mon May 26 |
\h | 本地机器的主机名,但是不带域名 |
\H | 完整的主机名 |
\j | 当前 shell 会话中进行的任务个数 |
\l | 当前终端设备的名称 |
\n | 换行符 |
\r | 回车符 |
\s | shell 程序的名称 |
\t | 当前时间 (24小时制) ,格式为小时,分钟,秒 |
\T | 当前时间 (12小时制) |
@ | 当前时间 (12小时制,格式为 AM/PM) |
\A | 当前 (24小时制) ,格式为小时:分钟 |
\u | 当前用户的用户名 |
\v | shell 的版本号 |
\V | shell 的版本号和发行号 |
\w | 当前工作目录名 |
\W | 当前工作目录名称的最后一部分 |
! | 当前命令的历史编号 |
# | 当前 shell 会话中输入的命令数 |
$ | 在非管理权限下输出 $ 。在管理员权限下输出 # |
\[ | 标志一个或多个非打印字符序列的开始。用于嵌入非打印的控制字符,使其以一定方式操纵终端仿真器,比如移动光标或更改文本颜色 |
\] | 标志着非显示字符序列的结束 |
尝试设计提示符
- 通过这个特殊字符列表,我们可以更改提示符来查看效果。我们首先备份现有的字符串,以便过后进行恢复。
- 为此,将现有的字符串复制到我们创建的另外一个 shell 变量中。
1
[me@linux ~]$ ps1_old="$PS1"
- 这样我们就创建了名为 ps1_old 的新变量,并将 PS1 的值赋给了 ps1_old 。我们可以使用 echo 命令来验证 PS1 的值确实已经被复制了。
1
2[me@linuxbox ~]$ echo $ps_old
[\u@\h \W]\$ - 在终端会话中,用户随时可以通过这个过程的逆操作来复原最初的提示符。
1
[me@linuxbox ~]$ PS1='$ps1_old'
- 现在一切准备就绪。接下来让我们看看如果提示符为空会发生什么。
1
[me@linuxbox ~]$ PS1=
- 若提示符为空,那么用户不会得到任何提示。根本就没有提示字符串嘛!尽管提示符就在那里,但是系统并不会显示。这样的提示看起来很令人困惑,所以现在将提示符设置为最简略的内容。
- 这样就好多了,至少现在用户知道自己在做什么了。可以注意到双引号中末尾的空格。当显示提示符时,这个空格会把美元符号和光标分隔开。
- 在提示符中添加一个铃声。
1
$ PS1="\a\$"
- 这样以来,每当系统显示提示符的时候,用户都会听到哔哔声。虽然这可能会使用户感到厌烦,但是在一些情况下可能会很有帮助,比如可以在一个耗时特别长的命令执行完毕通知用户。
- 接下来,我们试着创建一个信息丰富的提示符,其中包括主机名和当天的时间信息。
1
$ PS1="\A \h \$"
- 如果我们需要记录某些任务的执行时间,在提示符中添加时间信息会比较有用。最后,我们定制一个类似于最初样式的提示符。
1
217:37 linuxbox $ PS1="<\u@\h \W>\$"
<me@linuxbox ~>$
添加颜色
- 基本介绍
- 大多数终端都会响应某些非打印字符序列,来控制光标位置、字符属性 (如颜色、粗体、文本闪烁等) 内容。
- 字符颜色是由发送到终端仿真器的一个 ANSI 转移代码来控制的,该转义代码嵌入到了要显示的字符流中。控制代码不会打印到屏幕上,而是被中断解释为一条指令。
- 在之前的表中可以看到,\[ 和 \] 这两个序列用来封装非打印字符串。一个 ANSI 转义代码以八进制 033 (该代码由转义键 [escape key] 产生开始) ,后面跟着一个可选的字符属性,之后是一条指令。
- 例如,将文本颜色设置为正常 (attribute=0) 、黑色的代码是\033[0;30m 。
- 设置文本颜色的转义序列
字符序列 | 文本颜色 |
---|---|
\033[0;30m | 黑色 |
\033[0;31m | 红色 |
\033[0;32m | 绿色 |
\033[0;33m | 棕色 |
\033[0;34m | 蓝色 |
\033[0;35m | 紫色 |
\033[0;36m | 青色 |
\033[0;37m | 淡灰色 |
\033[1;30m | 深灰色 |
\033[1;31m | 淡红色 |
\033[1;32m | 淡绿色 |
\033[1;33m | 黄色 |
\033[1;34m | 淡蓝色 |
\033[1;35m | 淡紫色 |
\033[1;36m | 淡青色 |
\033[1;37m | 白色 |
- 案例一
- 现在让我们尝试创造红色的提示符 (本书中表现为灰色) 。我们将相应的转义代码插入提示符的开端。
1
2<me@linuxbox ~>$ PS1 = "\[\033[0;31m\]<\u@\h \W>\$"
<me@linuxbox ~> - 事实证明操作可行,但是此时用户输入的所有文字也变成红色。要修复这个问题,可以在提示符的末尾插入一条转移码,以通知终端仿真器回复到原来的颜色。
1
2<me@linuxbox ~>$ PS1="\[\033[0;31m\]<\u@\h \W>\$\[\033[0m\"
<me@linuxbox ~>$
- 设置背景颜色的转义序列
字符序列 | 背景颜色 |
---|---|
\033[0;40m | 黑色 |
\033[0;41m | 红色 |
\033[0;42m | 绿色 |
\033[0;43m | 棕色 |
\033[0;44m | 蓝色 |
\033[0;45m | 紫色 |
\033[0;46m | 青色 |
\033[0;47m | 淡灰色 |
- 案例二
- 通过为第一个转义代码做一些修改,就可以创建带有红色背景的提示符。
1
<me@linuxbox ~>$ PS1="\[\033[0;41m\]<\u@h \W>\$\[\033[0m\]]"
- 用户除了正常 (0) 和粗体 (1) 属性外,还可以设置为下划线 (4) 、闪烁 (5) 和斜体 (7) 。
移动光标
- 基本介绍
- 转义代码也可以用来定位光标。比如在提示符出现的时候,这些转义代码通常用来在屏幕的不同位置 (比如屏幕上方的一角) 显示一个时钟或其他信息。
- 光标移动转义序列
转义码 | 动作 |
---|---|
\033[1;cH | 将光标移动至 1 行 c 列 |
\033[nA | 将光标向上移动 n 行 |
\033[nB | 将光标向下移动 n 行 |
\033[nC | 将光标向前移动 n 个字符 |
\033[nD | 将光标向后移动 n 个字符 |
\033[2J | 清空屏幕并将光标移动至左上角 (第 0 行第 0 列) |
\033[K | 清空当前光标位置到行末的内容 |
\033[s | 存储当前光标位置 |
\033[u | 恢复之前存储的光标位置 |
- 案例
- 通过使用这些代码,用户可以构建这样的一条提示符。每当提示符出现时,屏幕的上方会绘制出一个红色的横条,横条中有用黄色文本显示的时间。用于提示符的编码就是一个看起来很可怕的字符串:
1
PS1="\[\033[s\033[0;0H\033[0;41m\033[K\033[1;33m\t\033[Om\033[u\]<\u@\h \W>\$"
- 复杂提示符的分解
字符序列 | 动作 |
---|---|
\[ | 开始一个非打印字符序列。其真正目的是为了让 bash 正确计算可见提示符的长度。如果没有该字符,命令行编辑功能无法正确定位光标 |
\033[s | 存储光标位置。在屏幕的顶部横条绘制完成并显示时间后,读取并使光标返回此位置。需要注意的是,一些终端仿真器不支持该代码 |
\033[0;0H] | 将光标移动至左上角,即第 0 行第 0 列 |
\033[0;41m] | 将背景颜色设置为红色 |
\033[K | 将光标当前位置 (左上角) 到行末的内容清空。因为现在背景颜色已经是红色了,所以清空后的行就是红色,也就会绘出了红色的横条。需要注意的是清空行的内容并不会改变光标的位置,光标仍处于屏幕左上角 |
\033[1;33m | 将文本颜色设置为黄色 |
\t | 显示当前时间。尽管这是一个可打印的元素,但是还是将其包含在提示符非打印部分中,这是因为 bash 在计算可见提示符的长度时,不应当将其计算在内 |
\033[0m | 关闭颜色。对文本和背景均有效 |
\033[u | 恢复之前存储的光标位置 |
\] | 结束非打印的字符序列 |
<\u@\h \W>$ | 提示符字符串 |
保存提示符
- 很显然,用户不会想要每次都输入这样一长串代码,所以就需要将提示符存储在某个地方。将提示符添加到 .bashrc 文件中是一个一劳永逸的解决方法。也就是将以下两行代码添加到文件中。
1
2PS1="\[\033[s\033[0;0H\033[0;41m\033[K\033[1;33m\t\033[Om\033[u\]<\u@\h \W>\$"
export PS1
参考文章
- 转载:Linux 命令行大全
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment
TwikooGitalk