Shell printf格式化输出命令

printf 是 awk 的重要格式化输出命令,本节我们先介绍一下 printf 命令如何使用。

需要注意,在 awk 中可以识别 print 输出动作和 printf 输出动作(区别是:print 会在每个输出之后自动加入一个换行符;而 printf 是标准格式输出命令,并不会自动加入换行符,如果需要换行,则需要手工加入换行符),但是在 Bash 中只能识别标准格式化输出命令 printf。所以我们在本小节中介绍的是标准格式化输出命令 printf。

printf 命令格式如下:

[root@localhost ~]# printf '输出类型输出格式' 输出内容

输出类型:
  • %ns:输出字符串。n 是数字,指代输出几个字符;
  • %ni:输出整数。n 是数字,指代输出几个数字‘’
  • %m.nf: 输出浮点数。m 和 n 是数字,指代输出的整数位数和小数位数。如 %8.2f 代表共输出 8 位数,其中 2 位是小数,6 位是整数;

输出格式:
  • \a: 输出警告声音;
  • \b:输出退格键,也就是 Backspaced 键;
  • \f:清除屏幕;
  • \n:换行;
  • \r:回车,也就是 Enter 键;
  • \t:水平输出退格键,也就是 Tab 键;
  • \v:垂直输出退格键,也就是 Tab 键;

为了演示 printf 命令,我们需要修改一下刚刚 cut 命令使用的 student.txt 文件。文件内容如下:

[root@localhost ~]# vi student.txt
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66

我们使用 printf 命令输出这个文件的内容,如下:

[root@localhost ~]# printf '%s' $(cat student.txt)
IDNamegenderPHPUnuxMySQl_Average1LjmingM82 958687.662ScM74968785.663GaoM998393 91.66
[root@localhost ~]#

输出结果十分混乱。这就是 printf 命令,如果不指定输出格式,则会把所有输出内容连在一起输出。其实文本的输出本身就是这样的,cat 等文本输出命令之所以可以按照格式漂亮地输出,那是因为 cat 命令已经设定了输出格式。

那么,为了用 printf 输出合理的格式,应该这样做:

[root@localhost ~]# printf '%s\t %s\t %s\t %s\t %s\t %s\t\n' $(cat student.txt)
#注意:在printf命令的单引号中只能识别格式输出符号,而手工输入的空格是无效的
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66

再强调一下:在 printf 命令的单引号中输入的任何空格都不会反映到格式输出中,只有格式输出符号才能影响 printf 命令的输出结果。

解释一下这个命令:因为我们的文档有6列,所以使用 6 个"%s"代表这 6 列字符串,每个字符串之间用"\t"分隔;最后还要加入"\n",使得每行输出都换行,否则这些数据还是会连成一行的。

如果不想把成绩当成字符串输出,而是按照整型和浮点型输出,则要这样做:

[root@localhost ~]# printf '%i\t %s\t %i\t %i\t %i\t %8.2f\t\n'\
$(cat student.txt | grep -v Name)
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66

先解释"cat student.txt|grep -v Name"这条命令。这条命令会把第一行标题取消,剩余的内容才用 printf 格式化输出。在剩余的内容中,第 1、3、4、5 列为整型,所以用"%i"输出;而第 2 列是字符串,所以用"%s"输出;而第 6 列是小数,所以用"%8.2f"输出。"%8.2f"代表可以输出 8 位数,其中有 2 位是小数,有 6 位是整数。

printf 命令是 awk 中重要的输出动作,不过 awk 中也能识别 print 动作,区别刚刚已经介绍了,当然稍后我们还会举例来说明一下这两个动作的区别。注意:在 Bash 中只有 printf 命令。另外,printf 命令只能格式化输出具体数据,不能直接输出文件内容或使用管道符,所以 printf 命令的格式还是比较特殊的。