终端作为交互式工具,用户可以通过它与shell环境进行交互。在终端中打印文本是绝大多数shell脚本和工具日常需要的基本任务。能够执行打印的方法有很多,格式也各有不同。
一. echo命令
echo是用于终端打印的基本命令。Shell中的echo指令与PHP的echo指令类似,都是用于字符串的输出。
- 显示普通字符串
默认情况下,echo在每次调用后会添加一个换行符。(双引号、单引号和直接输出,效果一致)
$ echo "Hello world"
Hello world
$ echo 'Hello world'
Hello world
$ echo Hello world
Hello world
这些方法看起来相似,但各有一些特殊用途和副作用。如下面这行命令:
$ echo Hello world!
Hello world!
$ echo 'Hello world!'
Hello world!
$ echo "Hello world!"
-bash: !": event not found
这是由于 H - histexpand 模式打开了导致。命令行下,双引号里面用了 ! 的话,Shell 会以为要执行历史展开,从而导致报错。
解决方法:(set +H关闭histexpand)
$ echo $-
himBH
$ set +H
$ echo $-
himB
$ echo "Hello world!"
在echo中使用带双引号的文本时,应该在echo之前使用set +H,以便能够正常使用。
每种方法的副作用:
- 使用不带引号的echo时,没法在所要显示的文本中使用,因为在bash shell中被用作命令定界符。
- 以echo hello;hello为例,echo hello被视为一个命令,第二个hello则被视为另一个命令。
- 使用带单引号的echo时,Bash不会对单引号中的变量(如$var)求值,而只是照原样显示。
这意味着:$ echo '$var'将会返回 $var,而$ echo $var将会根据变量$var定义与否,返回其值,或者什么都不返回。
- 显示转义字符
在默认情况下,echo会将一个换行符追加到输出文本的尾部。可以使用标志-n或转义字符\c来忽略结尾的换行符。
如果需要使用转义序列,则采用echo -e "包含转义序列的字符串"这种形式。例如:
xx:~ xx$ echo -n "Hello world "
Hello world xx:~ xx$
xx:~ xx$ echo "1\t2\t3"
1\t2\t3
xx:~ xx$ echo -e "1\t2\t3"
1 2 3
xx:~ xx$ echo -e "Hello world \c"
Hello world xx:~ xx$
二. printf命令
printf命令模仿C程序库中的printf(),使用的参数和C语言中的printf函数一样。例如:
$ printf "Hello world\n"
在默认情况下,printf并不像echo命令一样会自动添加换行符,必须在需要的时候手动添加,如上Hello world后面添加\n,如下面的脚本:
#!/bin/bash
#文件名:printf.sh
printf "%-5s %-10s %-4s\n" No Name Mask
printf "%-5s %-10s %-4.2f\n" 1 Zhangsan 87.54323
printf "%-5s %-10s %-4.2f\n" 2 Lisi 90.04432
printf "%-5s %-10s %-4.2f\n" 3 Wangwu 89.527
我们会得到如下格式的输出:
No Name Mask
1 Zhangsan 87.54
2 Lisi 90.04
3 Wangwu 89.53
%s、%c、%d和%f都是格式替代符(format substitution character),其所对应的参数可以置于带引号的格式字符串之后。
%-5s指明了一个格式为左对齐且宽度为5的字符串替代(-表示左对齐)。如果不用-指定对齐方式,字符串将采用右对齐方式。
对Name而言,保留宽度是10,其内容都会被显示在10字符宽的保留区域内,如不足10字符,则用空格符填充。
对于Mark字段,我们将其格式化为%-4.2f,其中.2指定保留2位小数位。
三. 补充内容
需要注意的是:
echo和printf中的标志(如-e -n等)应该出现在命令行内任何字符串之前,否则Bash会将其视为另外一个字符串。