shell 之 echo 与 printf 和颜色

printf 和 echo

printf 命令模仿 C 程序库(library)里的 printf() 库程序(library routine)。它几乎复制了该函数的所有功能。

不过在 Shell 层级的版本上,会有些差异。由于 printf 的行为是由 POSIX标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。 如同 echo 命令,printf 命令可以输出简单的字符串:

[root@master ~]#printf "Hello, Shell\n"
Hello, Shell
[root@master ~]#

你应该可以马上发现,最大的不同在于:printf 不像 echo 那样会自动提供一个换行符号。你必须显式 地将换行符号指定成 \n

echo -n "Enter your name:" // 参数 - n 的作用是不换行,echo 默认是换行

要使转义符生效,需加参数 -e

echo 输出颜色文本

echo 命令改变样式,以输出不同颜色的文本,必须有 -e 选项 (开启 echo 中的转义)。

在 echo 命令输出之后附加换行,可以使用 n 选项:

$ cat >echo
#!/bin/bash
echo -e "this echo's 2 new lines\n\n"
echo "OK"
echo "The log files have all been done"
echo "$LOGNAME carried them out at `date`"
echo "\"/dev/rmt0"\"

echo "/dev/rmt0"
/dev/rmt0
echo "\"/dev/rmt0\""
"/dev/rmt0"

菜单显示,不必多个 echo 一行行显示,可以一整个 echo

echo "===========================================
|           ** unix script test              |
|           1 --- num 1                       |
|           2 --- num 2                       |
|           3 --- num 3                       |
|           4 --- num 4                       |
==============================================="

事实上,echo 除了 -n options 之外,常用选项还有: -e :启用反斜线控制字符的转换 (参考下表) -E :关闭反斜线控制字符的转换 (预设如此) -n :取消行末之换行符号 (与 -e 选项下的 c 字符同意)

前面讲到,包围在单引号之内的字符都不会有特殊含义,所以单引号本身并不能在一对单引号中出现。但是在前面加上 $ 之后,就可以使用 \ 进行转义了,\ 的转义含义与 C 语言中的相同。

关于 echo 命令所支持的反斜线控制字符如下表:

例一:

$ echo -e "a\tb\tc\nd\te\tf"
a b c
d e f

上例运用 \t 来区隔 abc 还有 def ,及用 \ n 将 def 换至下一行。

例二:

$ echo -e "\141\011\142\011\143\012\144\011\145\011\146"
a b c
d e f

与例一的结果一样,只是使用 ASCII 八进位编码。

例三:

$ echo -e "\x61\x09\x62\x09\x63\x0a\x64\x09\x65\x09\x66"
a b c
d e f

与例二差不多,只是这次换用 ASCII 十六进制编码。

测试变量是否已经设置

有时要测试是否已设置或初始化变量。如果未设置或初始化,就可以使用另一值。此命令格式为:

$ {variable : -value}

意即如果设置了变量值,则使用它,如果未设置,则取新值。例如:

$ COLOUR=blue
$ echo "The sky is ${COLOR:-grey} today"
The sky is grey today

变量 colour 取值 blue,echo 打印变量 colour 时,首先查看其是否已赋值,如果查到,则使用该值。变量 $COLOR 没有设置,所以会打印后面的 grey.

上面的例子并没有将实际值传给变量,需使用下述命令完成此功能:

$ {variable : = value}

下面是一个更实用的例子。查询工资清单应用的运行时间及清单类型。在运行时间及类 型输入时,敲回车键表明用户并没有设置两个变量值,将使用缺省值( 0 3:00 和 Weekly),并 传入 at 命令中以按时启动作业。

#!/bin/bash
# vartest
echo "what time do you wish start the payroll [03:00]:"
read TIME
echo "process to start at ${TIME:=03:00} OK"
echo "Is it a monthly or weekly run [Weekly]:"
read RUN_TYPE
echo "Run type is ${RUN_TYPE:=Weekly}'
at -f $RUN_TYPE $TIME

在输入域敲回车键,输出结果如下:

what time do you wish start the payroll [03:00]:

process to start at 03:00 OK
Is it a monthly or weekly run [Weekly]:

Run type is Weekly

在使用 putty、secureCRT、XShell 等终端仿真器连接 linux 系统时,ls、vim 等工具的输出都含有各种颜色,这些颜色的输出大大地增强了文本的可读性。

通常我们可以使用 echo 命令加 - e 选项输出各种颜色的文本,例如:echo -e "\033[31mRed Text\033[0m",可以输出红色的字体 “Red Text”。其中:”\033[31m” 和 “\033[0m” 是 ANSI 转义序列(ANSI escape code/sequence),它控制文本输出的格式、颜色等,大多数的类 unix 终端仿真器都能够解释 ANSI 转义序列。

1. ANSI 颜色序列格式

通用的控制文本颜色的转义序列格式如下:

CSI n1 [;n2 [;…]] m

其中 CSI 全称为 “控制序列引导器”(Control Sequence Introducer/Initiator),也就是上述示例中的 “\033[“(其中 \ 033 是你键盘左上角 Esc 键对应的 ascii 码(八进制))

注:\033 是键盘左上角 Esc 键对应的 ASCII 码(8 进制),\033、\x1b 和 \ e 效果一样, 例如:echo -e “\x1b[31mRed Text\e[0m” 也输出红色字体 “Red Text”。

除了 shell 命令可输出颜色,其它语言中也可以使用上述 ANSI 转义序列输出颜色(前提是你使用的终端仿真器能够解析 ANSI 转义序列),以下给出几种主要语言中输出颜色文本的示例。

注:以下程序仅针对类 unix 终端有效,win32 控制台不支持 ANSI 转义序列,因而无效。

常用的 SRG 参数列表如下:

可以选择的编码如下所示 (这些颜色是 ANSI 标准颜色):

编码 颜色 / 动作
0   重新设置属性到缺省设置
1   设置粗体
2   设置一半亮度 (模拟彩色显示器的颜色)
4   设置下划线 (模拟彩色显示器的颜色)
5   设置闪烁
7   设置反向图象
22   设置一般密度
24   关闭下划线
25   关闭闪烁
27   关闭反向图象
30   设置黑色前景
31   设置红色前景
32   设置绿色前景
33   设置黄色前景
34   设置蓝色前景
35   设置紫色前景
36   设置青色前景
37   设置白色 (灰色) 前景
38   在缺省的前景颜色上设置下划线
39   在缺省的前景颜色上关闭下划线
40   设置黑色背景
41   设置红色背景
42   设置绿色背景
43   设置黄色背景
44   设置蓝色背景
45   设置紫色背景
46   设置青色背景
47   设置白色 (灰色) 背景
49   设置缺省黑色背景
\033[2J   清除屏幕
\033[0q   关闭所有的键盘指示灯
\033[1q   设置 “滚动锁定” 指示灯 (Scroll Lock)
\033[2q   设置 “数值锁定” 指示灯 (Num Lock)
\033[3q   设置 “大写锁定” 指示灯 (Caps Lock)
\033[15:40H   把关闭移动到第 15 行,40 列
\007   发蜂鸣生 beep
\a ASCII   响铃字符(也可以键入 \007)
\e ASCII   转义字符(也可以键入 \033)

\033 与 \e 是一样功能

下面看几个例子:

echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"


echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"
echo -e "\033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[0m"
echo -e "\033[44;37m 蓝底白字 \033[0m"
echo -e "\033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[0m"
echo -e "\033[47;30m 白底黑字 \033[0m"

控制选项说明 :

m 前面的 0 可以省略。

编码 说明
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m – 37m 设置前景色
\033[40m – 47m 设置背景色
\033[nA 光标上移 n 行
\033[nB 光标下移 n 行
\033[nC 光标右移 n 行
\033[nD 光标左移 n 行
\033[y;xH 设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标

顺序无关,只需要记忆数值所代表的含义即可,因为数值已经限定了是背景还是前景之类的

文本终端的显示颜色可以使用 “ANSI 非常规字符序列” 来生成。

例如:echo -e "\033[44;37;5m ME\033[0m COOL" 解释:“\033[44;37;5m ME”` 设置背景为蓝色,前景为白色,闪烁光标,输出字符 “ME”;

"\033[0m COOL" 重新设置屏幕到缺省设置,输出字符 “COOL”。

“e” 是命令 echo 的一个可选项,它用于激活特殊字符的解析器。”\033” 引导非常规字符序列 (即 “\033[” 表示终端转义字符开始,”\033” 即退出键 < ESC> 的 ASCII 码)。”m” 意味着设置属性然后结束非常规字符序列,这个例子里真正有效的字符是 “44;37;5” 和 “0”。修改 “44;37;5” 可以生成不同颜色的组合,数值和编码的前后顺序没有关系。

echo 显示带颜色,需要使用参数 - e 格式如下: echo -e "\033[字背景颜色; 文字颜色 m 字符串 \ 033[0m" 例如: echo -e "\033[41;37m TonyZhang \033[0m"

echo -e "\e[41;37m TonyZhang \e[0m"

其中 41 的位置代表底色, 37 的位置是代表字的颜色

注:

1、字背景颜色和文字颜色之间是英文的 “”“” 2、文字颜色后面有个 m 3、字符串前后可以没有空格,如果有的话,输出也是同样有空格

一些说明:

前景颜色各数字是对应背景颜色减去 10。 结束非常规字符序列的 “m” 要紧跟前面的数字,不能有空格。 命令也可以写成 echo -e “^[[44;37;5m ME \033[0m COOL”,其中的 “^[” 是先按 Ctrl-V, 然后再按 < ESC> 键产生的。 输出带有颜色的文本,echo 命令必须带有选项 “-e”。 这种方法只能暂时改变 echo 命令输出的文本的样式,logout 后就恢复为默认。修改. bashrc 文件,可以修改默认的显示样式。 如:在. bashrc 文件的最后面追加一行:echo -e ‘\033[47;30m’。

echo 命令的其他用法

光标跳到第 60 列,然后显示一个 OK。 格式:echo -en ‘\033[60G’ && echo OK 说明:”\033[” 是终端转义字符开始,60G 是命令。

添加颜色

添加颜色相当容易,第一步是设计不带颜色的提示行;

添加终端(而不是 bash)可识别的专用转义序列,以使它以彩色显示文本的某些部分。 标准 Linux 终端和 X 终端允许您设置前景(文字)颜色和背景颜色,如果需要,还可以启用 “bold” 字符。

有八种颜色可供我们选择。前景编号 (30-37) 和背景编号 (40-47) 颜色是通过在 PS1 中添加专用序列来选择的──基本上是夹在 “\e[“(转义开方括号)和 “m” 之间数字值。如果指定一个以上的数字代码,则用分号将它们分开。下面是一个颜色代码示例:”\e[0m”

如果将数字代码指定为零,则它就会通知终端将前景、背景和加粗设置重置为它们的默认值。您可能会在提示行结束时使用这个代码,以使您键入的文字成为非彩色的。

我已说明了如何在提示行中添加信息和颜色,但您还可以更进一步。您可以通过在提示行中添加专用代码来使 X 终端(如 rxvt 或 aterm)的标题栏得到动态更新。您所要做的只是将下面的序列添加到您的 PS1 提示行中:

"/e]2;titlebar/a"

只须用您希望其出现在 xterm 标题栏中的文字替换子串 “titlebar” 即可,现在已经一切就绪了!不必使用静态文字;您可以将 bash 转义序列插入标题栏中。请查看下面这个示例,它将用户名、主机名和当前工作目录显示在标题栏中,并定义了一个简短、明亮的绿色提示行:

export PS1="/[/e]2;/u@/H /w/a/e[32;1m/]>/[/e[0m/]"

因为它将全部信息显示在标题栏上,而不是显示在终端上,终端对一行可以显示多少字符有限制。

顺便提一句,确保用 “/[” 和 “/]” 将您的标题栏序列括起来(因为就终端而言,这个序列是非打印序列)。

将大量信息放在标题栏中的问题是,如果您使用非图形终端(如系统控制台),则看不到这些信息。

为了解决这个问题,可以在您的 .bashrc 中添加以下几行:

if ["$TERM" = "linux"]
then
#we're on the system console or maybe telnetting in
export PS1="/[/e[32;1m/]/u@/H > /[/e[0m/]"
else
#we're not on the console, assume an xterm
export PS1="/[/e]2;/u@/H /w/a/e[32;1m/]>/[/e[0m/]"
fi
-->