shell-guide

shell提示符

shell提示符由变量$PS1控制

我们默认的提示符看起来像这样:

sulihuangdeMacBook-Pro:~ Tracy$

注意它包含我们的用户名,主机名和当前工作目录,但是它又是怎样得到这些东西的呢? 结果证明非常简单。提示符是由一个环境变量定义的,叫做 PS1(是“prompt string one” 的简写)。我们可以通过 echo 命令来查看 PS1的内容。

sulihuangdeMacBook-Pro:~ Tracy$ echo $PS1
\h:\W \u\$

修改$PS1:

sulihuangdeMacBook-Pro:~ Tracy$ PS1='\[\e[0;31m\]\u\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \[\e[0;31m\]\$ \[\e[m\]\[\e[0;32m\] '

从输出结果中,我们看到那个 PS1 环境变量包含一些这样的字符,比方说中括号,@符号,和美元符号, 但是剩余部分就是个谜。我们中一些机敏的人会把这些看作是由反斜杠转义的特殊字符,就像我们 在第八章中看到的一样。这里是一部分字符列表,在提示符中 shell 会特殊对待这些字符:

Shell 提示符中用到的转义字符

序列 显示值
\a 以 ASCII 格式编码的铃声 . 当遇到这个转义序列时,计算机会发出嗡嗡的响声。
\d 以日,月,天格式来表示当前日期。例如,“Mon May 26.”
\h 本地机的主机名,但不带末尾的域名。
\H 完整的主机名。
\j 运行在当前 shell 会话中的工作数。
\l 当前终端设备名。
\n 一个换行符。
\r 一个回车符。
\s shell 程序名。
\t 24小时制当前时间,格式为 HH:MM:SS
\T 12小时制当前时间,格式为 HH:MM:SS。
\@ 12小时制当前时间,格式为am/pm
\A 24小时制当前时间,格式为 HH:MM。
\u 当前用户名。
0\v shell 程序的版本号。
\V shell发行备注,版本号+补丁
\w 当前工作目录名。
\W 当前工作目录名的最后部分。
\! 当前命令的历史号。
\# 当前 shell 会话中的命令数
\$ 这会显示一个"$"字符,除非你拥有超级用户权限。在那种情况下, 它会显示一个"#"字符。
\[ 标志着一系列一个或多个非打印字符的开始。这被用来嵌入非打印 的控制字符,这些字符以某种方式来操作终端仿真器,比方说移动光标或者是更改文本颜色。
\] 标志着非打印字符序列结束。

修改提示符

修改前备份默认提示符,有备无患。

sulihuangdeMacBook-Pro:~ Tracy$  ps1_base="$PS1"

在终端会话中,我们能在任一时间复原提示符,只要简单地反向操作就可以了。

sulihuangdeMacBook-Pro:~ Tracy$  PS1="$ps1_base"

现在就可以尽情的施展我们的才华和想象力来创造属于自己的提示符

sulihuangdeMacBook-Pro:~ Tracy$  PS1="\u :\h \$ "

添加颜色

大多数终端仿真器程序支持一定的非打印字符序列来控制,比方说字符属性(像颜色,黑体和可怕的闪烁) 和光标位置。我们会更深入地讨论光标位置,但首先我们要看一下字体颜色。

字符颜色是由发送到终端仿真器的一个嵌入到了要显示的字符流中的 ANSI 转义编码来控制的。 这个控制编码不会“打印”到屏幕上,而是被终端解释为一个指令。正如我们在上表看到的字符序列, 这个 [ 和 ] 序列被用来封装这些非打印字符。一个 ANSI 转义编码以一个八进制033(这个编码是由 退出按键产生的)开头,其后跟着一个可选的字符属性,在之后是一个指令。例如,把文本颜色 设为正常(attribute = 0),黑色文本的编码如下:

\033[0;30m

这里是一个可用的文本颜色列表。注意这些颜色被分为两组,由应用程序粗体字符属性(1) 分化开来,这个属性可以描绘出“浅”色文本。

用转义序列来设置文本颜色

序列 文本颜色 序列 文本颜色
\033[0;30m 黑色 \033[1;30m 深灰色
\033[0;31m 红色 \033[1;31m 浅红色
\033[0;32m 绿色 \033[1;32m 浅绿色
\033[0;33m 棕色 \033[1;33m 黄色
\033[0;34m 蓝色 \033[1;34m 浅蓝色
\033[0;35m 粉色 \033[1;35m 浅粉色
\033[0;36m 青色 \033[1;36m 浅青色
\033[0;37m 浅灰色 \033[1;37m 白色

让我们试着制作一个篮色提示符。我们将在开头加入转义编码:

sulihuangdeMacBook-Pro:~ Tracy$  PS1='\[\033[0;34m\]<\u@\h \W>\$'

我们的提示符生效了,但是注意我们在提示符之后输入的文本也是红色的。为了修改这个问题, 我们将添加另一个转义编码到这个提示符的末尾来告诉终端仿真器恢复到原来的颜色。

sulihuangdeMacBook-Pro:~ Tracy$  PS1='\[\033[0;34m\]<\u@\h \W>\$\[\033[0m\]'

设置文本的背景颜色,使用下面列出的转义编码。这个背景颜色不支持黑体属性。

用转义序列来设置背景颜色

序列 背景颜色 序列 背景颜色
\033[0;40m 蓝色 \033[1;44m 黑色
\033[0;41m 红色 \033[1;45m 粉色
\033[0;42m 绿色 \033[1;46m 清色
\033[0;43m 棕色 \033[1;47m 浅灰色

我们可以创建一个带有红色背景的提示符,只是对第一个转义编码做个简单的修改。

sulihuangdeMacBook-Pro:~ Tracy$  PS1='\[\033[0;41m\]<\u@\h \W>\$\[\033[0m\] '

注意:除了正常的 (0) 和黑体 (1) 字符属性之外,文本也可以具有下划线 (4),闪烁 (5), 和反向 (7) 属性。为了拥有好品味,然而,许多终端仿真器拒绝使用这个闪烁属性。

移动光标

转义编码也可以用来定位光标。这些编码被普遍地用来,每次当提示符出现的时候,会在屏幕的不同位置 比如说上面一个角落,显示一个时钟或者其它一些信息。这里是一系列用来定位光标的转义编码: *光标移动转义序列

转义编码 行为
\033[l;cH 把光标移到第 l 行,第 c 列。
\033[nA 把光标向上移动 n 行。
\033[nB 把光标向下移动 n 行。
\033[nC 把光标向前移动 n 个字符。
\033[nD 把光标向后移动 n 个字符。
\033[2J 清空屏幕,把光标移到左上角(第零行,第零列)。
\033[K 清空从光标位置到当前行末的内容。
\033[s 存储当前光标位置。
\033[u 唤醒之前存储的光标位置。

使用上面的编码,我们将构建一个提示符,每次当这个提示符出现的时候,会在屏幕的上方画出一个 包含时钟(由黄色文本渲染)的红色长条。提示符的编码就是这个看起来令人敬畏的字符串

PS1='\[\033[s\033[0;0H\033[0;41m\033[K\033[1;33m\t\033[0m\033[u\]
<\u@\h \W>\$ '

让我们分别看一下这个字符串的每一部分所表示的意思:

序列 行动
\[ 开始一个非打印字符序列。其真正的目的是为了让 bash 能够正确地计算提示符的大小。如果没有这个转义字符的话,命令行编辑 功能会弄错光标的位置。
\033[s 存储光标位置。这个用来使光标能回到原来提示符的位置, 当长条和时钟显示到屏幕上方之后。当心一些 终端仿真器不推崇这个编码。
\033[0;0H 把光标移到屏幕左上角,也就是第零行,第零列的位置。
\033[0;41m 把背景设置为红色。
\033[K 清空从当前光标位置到行末的内容。因为现在 背景颜色是红色,则被清空行背景成为红色,以此来创建长条。注意虽然一直清空到行末, 但是不改变光标位置,它仍然在屏幕左上角
\033[1;33m 把文本颜色设为黄色。
\t 显示当前时间。虽然这是一个可“打印”的元素,但我们仍把它包含在提示符的非打印部分, 因为我们不想 bash 在计算可见提示符的真正大小时包括这个时钟在内。
\033[0m 关闭颜色设置。这对文本和背景都起作用。
\033[u 恢复到之前保存过的光标位置处。
\] 结束非打印字符序列。
<\u@\h \W>$ 提示符字符串。

保存提示符

显然地,我们不想总是敲入那个怪物,所以我们将要把这个提示符存储在某个地方。通过把它 添加到我们的.bashrc 文件,可以使这个提示符永久存在。为了达到目的,把下面这两行添加到.bashrc 文件中。

PS1='\[\033[s\033[0;0H\033[0;41m\033[K\033[1;33m\t\033[0m\033[u\]<\u@\h \W>\$ '
export PS1

参考文献