echo -e 中 -e 表示 enable interpretation of backslash escapes,即启用反斜杠\转义。
若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
字符
含义
\a
发出警告声;
\b
退格(backspace):光标向前移动一个字符;
\c
produce no further output: 这条echo命令中 \c 后面的部分都不打印出来,包括制表符,换行符,换页符都不打印,光标也保持在当前位置不移动。
\f
form feed换行,但是光标位置保持在下一行的当前列;
\n
换行,并且光标移至行首;
\r
回车(carriage return): 将光标位置移到本行开头(但是,如果想要不换行,应该使用 echo -ne "xxx\r");
\t
horizontal tab;
\v
vertical tab;光标竖直向下移动一行。类似按 ↓ 时的效果。换言之,光标换行,但是保持在当前列;效果类似 \f
\
插入\字符;
\0NNN
插入 NNN(八进制)所代表的ASCII字符;
\xHH
插入HH(十六进制)所代表的ASCII字符;
\b 退格
首先来测试一下 \b 的效果
#!/bin/bash
var=abc
echo $var
echo "$var\b"
echo -e "$var\b"
echo -e "$var\bd"
echo $var\b
echo -e $var\b
echo -e $var\\bd
打印结果如下:
abc
abc\b
abc
abd
abcb
abcb
abd
命令
打印结果
分析
echo $var
abc
(不做分析)
echo "$var\b"
abc\b
没有加转义参数 -e,所以\b原样输出
echo -e "$var\b"
abc
因为\b后面没有字符,所以 abc 还是 abc
echo -e "$var\bd"
abd
光标位置从原字符 c 的后面移到了 c 的前面,因此新输入的字符 d 即覆盖了字符 c。这也就是网上都说 \b 可以删除一个字符的原因
echo $var\becho -e $var\b
abcd
\被忽略了
echo -e $var\\bd
abd
这个例子说明不用双引号包裹字符串也可以,但是要用 \\b 来表示 \b
\c :produce no further output
接下来测试一下 \c 的效果
#!/bin/bash
echo "line 1"
echo "line 2"
echo -e "line 3\c"
echo "line 4"
打印结果如下:
[admin@centOS-01 ~]$ sh c.sh
line 1
line 2
line 3line 4
[admin@centOS-01 ~]$
我们发现两条 echo "line 1" 执行完,光标会自动换行且移动至行首位置。因此, echo "line 2" 会从第二行开始打印。
但是,当我们执行 echo -e "line 3\c" 时,就不会自动加上换行符号,光标也停留在当前位置(我猜c即current),那么 echo "line 4" 就会紧跟着字符 3 之后输出。
另外,不加双引号的写法如下:
echo -e line 3\\c
再来看一个例子,当 \c 不在字符串末尾时,末尾也不会加上换行符
#!/bin/bash
echo -e "a\c bcdefg"
输出结果为
[admin@centOS-01 ~]$ sh c.sh
a[admin@centOS-01 ~]$
我惊奇地发现 bcdefg 全都没有打印出来。
而且因为没有换行符的缘故。a 和 [admin@centOS-01 ~]$ 同一行显示了。
如果,如果是和 \c 不在同一条命令中字符串可以正常打印:
#!/bin/bash
echo -e "a\c\n"
echo bc
打印结果为
[admin@centOS-01 ~]$ sh c.sh
abc
[admin@centOS-01 ~]$
echo -e "a\c\n" 只打印出一个 a 字符,且光标就停留在 a 之后。
所以,在 \c 之后出现的,不管是 \n 还是 \t 都不会打印出来。
相反地,另一条命令 echo bc 还是正常在 a 之后打印出来了,并没有受到上一条命令的影响。
\f 换页符
如果使用 echo -e "\f" 效果并不好,因此我们使用 echo -ne "\f" 来测试。
-n 参数作用是 do not output the trailing new line,就是不自动在末尾加上换行符。
测试脚本如下:
#!/bin/bash
echo -ne "\f1"
echo -ne "2\f2"
echo -ne "333\f"
echo "444"
输出结果如下:
12
2333
444
当把 \f 放在行首时,就效果就等同于 \n。因此,echo -ne "\f1" 和 echo -ne "\n1" 效果是一样的。
当 \f 放在非行首位置,它会有 \n 的效果,而且会让光标移动到与当前位置相同的列。
这是由于这个特性,我觉得 \f 适合“阶梯式”打印,例如以下这段代码
#!/bin/bash
for i in 1 2 3 4 5
do
echo -ne $i\\f
done
输出效果如下:
1
2
3
4
5
\r 回车
\r (回车,Carriage Return)也是我觉得很有意思的一个参数,放在行尾时,可以用于“刷新(但又不完全刷新)当前行的文本”。
但是,最好也是使用 echo -ne "\r" ,才能发挥它的作用。
你们是否尝试过直接执行命令 echo -ne "abc\r"却没有任何效果?比如下面这样:
[admin@centOS-01 ~]$ echo -ne "abc\r"
[admin@centOS-01 ~]$
打印的字符串 abc 到哪里去了呢?其实是被后来出现的提示符字符串 [admin@centOS-01 ~]$ 给覆盖了,我这就给大家演示一下:
[admin@centOS-01 ~]$ echo -ne "abc"
abc[admin@centOS-01 ~]$
当我们不用 \r 而仅仅使用 echo -n 就会让打印字符串 abc 和命令提示符在同一行。
你是不是恍然大悟,当你打印的字符长度 < 命令提示符的长度时,打印字符就好像“没效果”似的,
但是,当你打印的字符长度 > 命令提示符的长度时,就会出现以下的结果:
[admin@centOS-01 ~]$ echo -ne "==================================\r"
[admin@centOS-01 ~]$ =============
当我们的打印的字符长度就是比较短的时候,该怎么让他能够显示呢?
我们可以用 sleep 1 让你想要打印的字符停留的时间更长一点,让我们的肉眼能够捕捉到!
#!/bin/bash
for i in 1 2 3 4 5
do
echo -ne "Line $i\r"
sleep 1
done
效果如下图所示:
需要注意的是,入股后输出的内容比先输出的长,会出现奇怪的打印结果:
#!/bin/bash
echo -ne "Hello World\r"
sleep 1
echo -ne "Xxx Zzz\r"
sleep 1
打印结果如下:
因为先打印的字符串 Hello World 比 Xxx Zzz 长,所以 echo -ne "Xxx Zzz\r" 显示的结果是 Xxx Zzzorld,这样诡异的结果。
因此,大家在实际编写 shell 脚本时要避免这种情况。
\t 和 \v 制表符
我们还是先看一段代码:
#!/bin/bash
echo -e "a\tb\tc\td"
echo -e "1\v2\v3"
打印结果如下:
a b c d
1
2
3
网上也有人说 \v 和 \f 相同,运行下面一段脚本:
#!/bin/bash
echo -ne "1\f"
echo -e "2\f"
echo -ne "1\v"
echo -e "2\v"
打印结果为
1
2
1
2
此时,\v 和 \f 居然产生了相同的效果。
按理说 \f 作为换页符,应该会将整个终端屏幕清空空,然后再输出内容。但是,并没有出现这个效果,感觉就像是削弱得和 \v 一样了。
\0NNN 和 \xHH :ASCII编码字符
[geekziyu@centOS-01 ~]$ echo -e "\0101"
A
[geekziyu@centOS-01 ~]$ echo -e "\x61"
a
\0101 表示将八进制数 101(即十进制 65)转义为对应 ASCII 字符代码表中的字符 A;
\x61 表示将十六进制数 61(即十进制 97)转义为对应 ASCII 字符代码表中的字符 a;
\n 换行符
#!/bin/bash
echo "1\n"
echo -e "2\n"
echo "3"
打印结果:
[admin@centOS-01 ~]$ sh next.sh
1\n
2
3
[admin@centOS-01 ~]$
换行符大家都应该很熟悉了,但是不要忘记加上 -e 参数。
如果没有用 -ne 而只是用了 -e,那么你就会发现 2 和 3 之间多出一个空行。