(转)printf命令详解

原文:https://www.cnblogs.com/machangwei-8/p/10354698.html

https://wangchujiang.com/linux-command/c/printf.html

目录

 


 

基础命令学习目录首页

 

本文是Linux Shell系列教程的第(八)篇,更多shell教程请看:Linux Shell系列教程

在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中,已经对Shell printf命令有了一个简略的介绍,本篇给大家详细介绍下Shell中的printf命令。

Shell printf命令

一、Shell printf命令语法

printf  format-string  [arguments...]

format-string为描述格式规格的字符串,用来描述输出的排列方式,最好为此字符串加上引号。此字符串包含按字面显示的字符以及格式声明,格式声明时特殊的占位符,用来描述如何显示相应的参数。

arguments是与格式声明相对应的参数列表,例如一系列的字符串或变量值。

格式声明由两部分组成:百分比符号(%)和指示符。

最常用的格式指示符有两个,%s用于字符串,而%d用于十进制整数。

格式字符串中,一般字符会按字面显示。转义序列则像echo那样,解释后再输出成相应的字符。格式声明以%符号开头,并以定义的字母集中的一个来结束,用来控制相应参数的输出。

二、Shell printf命令转义序列

Shell printf命令的转义序列如下表所示

序列  
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 不显示输出结果中任何结尾的换行字符,而且任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符都被忽略。
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\\ 反斜杠字符

三、Shell printf命令格式指示符

Shell printf命令的格式指示符如下表所示

符号 说明
%c ASCII字符.显示相对应参数的第一个字符
%d,%i 十进制整数
%E 浮点格式([-d].precisionE [+-dd])
%e 浮点格式([-d].precisione [+-dd])
%g %e或%f转换,看哪一个较短,则删除结尾的零
%G %E或%f转换,看哪一个较短,则删除结尾的零
%s 字符串
%u 不带正负号的十进制值
%x 不带正负号的十六进制.使用a至f表示10至15
%% 字面意义的%
%X 不带正负号的十六进制.使用A至F表示10至15

 

四、Shell printf命令精度格式指示符

Shell printf命令中精度格式指示符入下表所示

符号 含义
%d,%i,%o,%u,%x,%X 要打印的最小位数.当值的位数少于此数字时,会在前面补零.默认精度为1
%e,%E 要打印的最小位数.当值的位数少于此数字时,会在小数点后面补零,默认为精度为6.精度为0则表示不显示小数点小数点右边的位数
%f 小数点右边的位数
%g,%G 有效位数的最大数目
%s

要打印字符的最大数目

使用举例:

复制代码
复制代码
printf "%.5d\n" 15
输出:00015

printf "%.10s\n" "a very long string"
输出:a very lon

printf "%.2f\n" 123.4567
输出:123.46
复制代码
复制代码

五、Shell printf命令一些标识符

Shell printf命令的一些常用标识符如下表所示

字符 说明
将字段里已格式化的值向左对齐
空格 在正值前置一个空格,在负值前置一个负号
+ 总是在数值之前放置一个正号或负号,即便是正值也是
# 下列形式选择其一:%o有一个前置的o;
%x与%X分别前置的0x与0X;
%e,%E与%f总是在结果中有一个小数点;
%g与%G为没有结尾的零。
0 以零填补输出,而非空白.这仅发生在字段宽度大于转换后的情况

使用举例:

复制代码
复制代码
$printf "%-20s%-15s%10.2f\n" "Shan" "zhang" 35       
输出:Shan                zhang               35.00
%-20s表示一个左对齐、宽度为20个字符字符串格式,不足20个字符,右侧补充相应数量的空格符。
%-15s表示一个左对齐、宽度为15个字符字符串格式。
%10.2f表示右对齐、10个字符长度的浮点数,其中一个是小数点,小数点后面保留两位。

$printf "|%10s|\n" hello
输出:|     hello|
%10s表示右对齐,宽度为10的字符串,如不足是个字符串,左侧补充相应数量的空格数.

$printf "|%-10s|\n" hello
输出:|hello     |
和案例二比较一下

$printf "%x %#x\n" 15 15
输出:f 0xf
如果#标志和%x,%X搭配使用,在输出十六进制数字时,前面回家0x或者0X前缀.
使用标志符的作用主要是为了动态的指定宽度和精度.
复制代码
复制代码

六、Shell printf命令的一些综合示例

下面给大家总结了一些比较综合的例子,希望能够帮助大家学习Shell printf命令。

复制代码
复制代码
字符串向左向右对齐:
$printf "|%-10s| |%10s|\n" hello world
输出|hello     | |     world|

空白标志:
$printf "|% d| |% d|\n" 15 -15                 
输出:| 15| |-15|

+标志:
$printf "|%+d| |%+d|\n" 15 -15  
输出:|+15| |-15|

#标志:
$printf "%x || %#X\n" 15 15
输出:f || 0XF

0标志:
$printf "%05d\n" 15
输出:00015
复制代码
复制代码

对于转换指示符%b、%c与%s而言,相对应的参数都应为字符串。否则,他们会被解释为C语言的数字常数(开头的0位八进制,以及开头的0x与0X为十六进制)。

更进一步说,如果参数的第一个字符为单引号或双引号,则对应的数值是字符串的第二个字符的ASCII值,比如:

命令:printf “%s is %d \n” a “‘a”

输出:a is 97 

当参数多于格式指示符时,格式指示符会根据需要再利用。

这种做法在参数列表长度未知时非常方便。

例如来自通配符表达式,如果留在格式字符串里剩下的指示符比参数多时,如果是数值转换,则遗漏的值会被看做是零。

但如果是字符串转换,则被视为空字符串(虽然可以这么用,但比较好的方式应该是一一对应关系,即提供的参数数目和格式字符串数目相同)。

如果printf无法进行格式的转换,便返回一个非零的退出状态。

 

好了,对于Shell printf命令的详解就先进行到这里,printf是一个非常强大的命令,希望大家平时能够多多练习,争取熟练掌握。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

作用:按照我们指定的格式输出文本

语法格式

printf "FORMAT" , item1, item2, ...

printf的工作原理:
将printf后面的item作为参数逐个传递给"FORMAT"进行格式化后输出

(1) 必须指定FORMAT,
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT可以有多个,但是必须与后面的每个item指定格式符
    #printf "%s\n%s\n%s\n%4.2f\n%4.2f\n%4.2f\n" I love you 11 12.2 13.35
    一共6个item,所以就是必须有6个FORMAT。
    如果FORMAT数量少于item数量,则FORMAT的个数控制一次传多少个item处理。
    比如:#printf "%7s %7s\n" I love you 11 12.2 13.35   2个FROMAT 6个item,一次传2个处理
            I    love
            you      11
            12.2   13.35

格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
    #printf "%g\n" -1 10 100.15 123.14
    -1
    10
    100.15
    123.14

%e, %E:显示科学计数法数值
    #printf "%e\n" A -1 10 100.15 123.14
    -bash: printf: A: invalid number
    0.000000e+00
    -1.000000e+00
    1.000000e+01
    1.001500e+02
    1.231400e+02

%f:显示为浮点数
    #printf "%f\n" A -1 10 100.15 123.14
    -bash: printf: A: invalid number
    0.000000
    -1.000000
    10.000000
    100.150000
    123.140000

%g, %G:以科学计数法或浮点形式显示数值
    printf "%g\n" A -1 10 100.15 123.14
    -bash: printf: A: invalid number
    0
    -1
    10
    100.15
    123.14

%s:显示字符串

%u:无符号整数
    #printf "%u\n" A -1 10 100.15 123.14
    -bash: printf: A: invalid number
    0
    18446744073709551615
    10
    -bash: printf: 100.15: invalid number
    0
    -bash: printf: 123.14: invalid number
    0

%o 不带正负号的八进制值
%u 不带正负号的十进制值
%x 不带正负号的十六进制值,使用a至f表示10至15
%X 不带正负号的十六进制值,使用A至F表示10至15
%%: 显示%自身

 修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f 四舍五入
    #printf "%-3.1f\n" 10 100.15 123.14
    10.0
    100.2
    123.1

-: 左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d
I love you 11 12.2 13.33
分别用echo 和 printf 按空格分隔换行输出来看效果
#echo -e "I\n love\n you\n 11\n 12.2\n 13.33\n"
I
 love
 you
 11
 12.2
 13.33

#printf "%s\n" I love you 11 12.2 13.33
I
love
you
11
12.2
13.33
是不是再也不用头疼\n换行的逐个设置了?

但是,再进行复杂一点的格式化输出,echo就无法处理了
#printf "%s\n%s\n%s\n%4.2f\n%4.2f\n%4.2f\n" I love you 11 12.2 13.35
I
love
you
11.00
12.20
13.35

来一些实例:

为传入的参数增加一对 [] 参数在[ ] 内

#cat mod|xargs printf "[ %s ]\n"
[ 周瑜-法师-烽火赤壁 ]
[ 不知火舞-法师-必杀·忍蜂 ]
[ 铠-战士-不灭魔躯 ]
#awk -F : '{printf "username:%15s | UID: %10d\n------------------------------------------\n",$1,$3}' /etc/passwd
awk -F: '{printf "%-8s %8s",$1 $2}' passwd.txt
username:          rtkit | UID:        498
------------------------------------------
username:          pulse | UID:        497
------------------------------------------
username:            gdm | UID:         42
------------------------------------------
username:           hunk | UID:        500
------------------------------------------
想怎么样式就输出

修饰符对于数字的影响

#printf "%.3f\n" 123.456789 1234.56789
123.457
1234.568
当修饰符为%f时,控制小数点后的精度 .3 就是3位小数

#printf "%.6d\n" 123 1234
000123
001234
当修饰符为%d时,控制整数的位数,不足的在高位补0  .6 就是6位整数
------------------------------------------------------------------------------------------------------------------------------------

内建命令

概要

printf [-v var] format [arguments]
 

主要用途

  • 格式化参数并输出。

选项

-v var:将结果输出到变量var中而不是输出到标准输出。
 

参数

format:输出格式。

arguments:一到多个参数。

转义序列:除了支持printf(1)和printf(3)的转义序列,内建printf还支持以下转义序列:

%b       展开参数中的反斜杠转义字符。
%q       将参数扩起以用作shell输入。
%(fmt)T  根据strftime(3)中的转义字符来输出日期时间字符串。
 

返回值

返回状态为成功除非给出了非法选项、写错误、赋值错误。

例子

# %-5s 格式为左对齐且宽度为5的字符串代替('-'表示左对齐),不使用则默认右对齐。
# %-4.2f 格式为左对齐宽度为4,保留两位小数。

printf "%-5s %-10s %-4s\n" NO Name Mark
printf "%-5s %-10s %-4.2f\n" 01 Tom 90.3456
printf "%-5s %-10s %-4.2f\n" 02 Jack 89.2345
printf "%-5s %-10s %-4.2f\n" 03 Jeff 98.4323

# 输出
NO    Name       Mark
01    Tom        90.35
02    Jack       89.23
03    Jeff       98.43


# %b %q %(fmt)T 的例子。
# see it again with a newline.
printf "%s\n" 'hello world'
# 展开换行符,和上面的结果一样。
printf "%b" 'hello world\n'

printf '%q\n' 'a b c'
# 输出
a\ b\ c

# %z为时区,%n为换行符。
printf "%(%F %T %z%n)T"
# 输出
2019-09-10 01:48:07 +0000
 

注意

  1. 该命令是bash内建命令,相关的帮助信息请查看help命令。

外部命令

概要

printf FORMAT [ARGUMENT]...
printf OPTION
 

主要用途

  • 格式化参数并输出。

选项

--help 显示帮助信息并退出。
--version 显示版本信息并退出。
 

参数

format:输出格式。

arguments:一到多个参数。

在这里忽略了(%b %q),如果你安装的coreutils版本支持它们,那么请参考上面的例子。
支持的转义序列:

\"          双引号
\\          反斜杠
\a          响铃
\b          退格
\c          截断输出
\e          退出
\f          翻页
\n          换行
\r          回车
\t          水平制表符
\v          竖直制表符
\NNN        八进制数 (1到3位数字)
\xHH        十六进制数 (1到2位数字)
\uHHHH      Unicode字符附加4位十六进制数字
\UHHHHHHHH  Unicode字符附加8位十六进制数字
%%          百分号

以及'diouxXfeEgGcs'中的一个结尾的C格式规范,将被转换为正确的类型并处理可变宽度。
 

例子

# 使用 /usr/bin/printf 确保调用的不是内建命令。
# 当然,在你关闭内建printf以及确认当前环境没有printf函数的情况下,可直接使用printf,详见末尾"注意"的链接。

# 按行打印数组和关联数组的下标及值。

# 声明数组可以不加'declare -a'或'local -a'(在函数内声明的局部变量)。
arr=('line1' 'line2')
/usr/bin/printf "%s\n" ${!arr[@]}
# 输出下标
0
1
/usr/bin/printf "%s\n" ${arr[@]}
# 输出值
line1
line2

#声明关联数组(也就是字典)必须加'declare -A'或'local -A'(在函数内声明的局部变量)。
declare -A assoc_arr=(['key1']='value1' ['key2']='value2')
/usr/bin/printf "%s\n" ${!assoc_arr[@]}
# 输出键。
key2
key1
/usr/bin/printf "%s\n" ${assoc_arr[@]}
# 输出值。
value2
value1
 

返回值

返回状态为成功除非给出了非法选项等。

注意

  1. 该命令是GNU coreutils包中的命令,相关的帮助信息请查看man -s 1 printfinfo coreutils 'pwd invocation'

  2. 启动或关闭内建命令请查看enable命令,关于同名优先级的问题请查看builtin命令的例子部分的相关讨论。

  3. 我通过和bug-bash@gnu.org的交流,得到了关于这几个格式说明符%b %q %(fmt)T的解释:

    printf(1)中的%b格式说明符是printf(3)支持的格式之外增加的一个POSIX特性。

    %q和%T说明符是非标准的,并且不受所有独立实现的printf的支持。

 
posted @ 2021-08-03 17:55  liujiacai  阅读(429)  评论(0编辑  收藏  举报