85. 使用 printf 进行漂亮的打印
printf
非常灵活,允许您按照您想要的方式打印输出,从而使报告打印工作相对容易。
语法:
printf "print format", variable1, variable2, etc.
printf
格式中的特殊字符
以下是一些可以在 printf
中使用的特殊字符。
特殊字符 | 解释 |
---|---|
\n |
新行 |
\t |
制表符 |
\v |
垂直制表符 |
\b |
退格键 |
\r |
回车 |
\f |
换页 |
以下使用换行符在单独的行中打印 "Line 1"
和 "Line 2"
:
$ awk 'BEGIN { printf "Line 1\nLine 2\n" }'
Line 1
Line 2
以下打印由制表符分隔的不同字段,其中 "Field 1"
后有 2 个制表符:
$ awk 'BEGIN { printf "Field 1\t\tField 2\tField 3\tField 4\n" }'
Field 1 Field 2 Field 3 Field 4
以下在每个字段后打印垂直制表符:
$ awk 'BEGIN { printf "Field 1\vField 2\vField 3\vField 4\n" }'
Field 1
Field 2
Field 3
Field 4
以下代码在除 "Field 4"
之外的每个字段后打印一个退格键。
这将删除前三个字段中每个字段中的最后一个数字。例如 "Field 1"
显示为 "Field"
,因为最后一个字符被退格键删除。
然而,最后一个字段 "Field 4"
按原样显示,因为 "Field 4"
后面没有 \b
。
$ awk 'BEGIN { printf "Field 1\bField 2\bField 3\bField 4\n" }'
Field Field Field Field 4
在下面的示例中,打印每个字段后,我们执行 "回车"
并在当前打印值之上打印下一个值。
这意味着,在最终输出中您看到的只是 "Field 4"
,因为它是在所有先前字段之上打印的最后一个内容。
$ awk 'BEGIN { printf "Field 1\rField 2\rField 3\rField 4\n" }'
Field 4
print
使用 OFS
、ORS
内置变量
当您使用 print
命令(不是 printf
)打印以逗号分隔的多个值时,它使用
OFS
和
ORS
内置变量值来决定如何打印字段。
以下示例显示了简单的打印语句 "print $2,$3"
如何受到使用
OFS
和
ORS
值的影响。
$ cat print.awk
BEGIN {
FS=",";
OFS=":";
ORS="\n--\n";
}
{
print $2,$3
}
$ awk -f print.awk items.txt
HD Camcorder:Video
--
Refrigerator:Appliance
--
MP3 Player:Audio
--
Tennis Racket:Sports
--
Laser Printer:Office
--
printf
不使用 OFS
、ORS
内置变量
printf
OFS
和
ORS
变量。 它仅使用 printf
命令的 "format"
字段中指定的内容,如下例所示。
$ cat printf1.awk
BEGIN {
FS=",";
OFS=":";
ORS="\n--\n";
}
{
printf "%s^^%s\n\n", $2, $3
}
$ awk -f printf1.awk items.txt
HD Camcorder^^Video
Refrigerator^^Appliance
MP3 Player^^Audio
Tennis Racket^^Sports
Laser Printer^^Office
printf
格式说明符。
格式字符 | 解释 |
---|---|
s |
字符串 |
c |
单个字符 |
d |
十进制 |
e |
指数浮点 |
f |
固定浮点数 |
g |
使用 e 或 f ,具体取决于给定输入中较小的一个 |
o |
八进制 |
x |
十六进制 |
% |
打印百分比符号 |
以下示例显示了格式说明符的基本用法:
$ cat printf-format.awk
BEGIN {
printf "s--> %s\n", "String"
printf "c--> %c\n", "String"
printf "s--> %s\n", 101.23
printf "d--> %d\n", 101.23
printf "e--> %e\n", 101.23
printf "f--> %f\n", 101.23
printf "g--> %g\n", 101.23
printf "o--> %o\n", 0x8
printf "x--> %x\n", 16
printf "percentage--> %%\n", 17
}
$ awk -f printf-format.awk
s--> String
c--> S
s--> 101.23
d--> 101
e--> 1.012300e+02
f--> 101.230000
g--> 101.23
o--> 10
x--> 10
percentage--> %
以固定列宽打印(基本)
要创建固定列宽报告,您必须在格式说明符中的 %
之后指定一个数字。该数字表示要打印的最小字符数。当输入字符串小于指定数量时,会在左侧添加空格以使其固定宽度。
以下示例显示 printf
语句的基本用法,并在%
% 后立即指定数字
$ cat printf-width.awk
BEGIN {
FS=","
printf "%3s\t%10s\t%10s\t%5s\t%3s\n","Num","Description","Type","Price","Qty"
printf "-----------------------------------------------------\n"
}
{
printf "%3d\t%10s\t%10s\t%g\t%d\n", $1,$2,$3,$4,$5
}
$ awk -f printf-width.awk items.txt
Num Description Type Price Qty
-----------------------------------------------------
101 HD Camcorder Video 210 10
102 Refrigerator Appliance 850 2
103 MP3 Player Audio 270 15
104 Tennis Racket Sports 190 20
105 Laser Printer Office 475 5
如果即使输入字符串比指定的数字长,您也想打印固定的列宽,则应使用 substr
函数(或)在格式标识符中的数字前添加小数(稍后解释)。
在前面的示例中,第二个字段比指定的 10 个字符宽度宽,因此结果不是预期的结果。
左侧添加空格以将 "Good"
打印为 6 个字符的字符串:
$ awk 'BEGIN { printf "%6s\n", "Good" }'
Good
即使您指定了 6 个字符宽度,也会在此处打印整个字符串:
$ awk 'BEGIN { printf "%6s\n", "Good Boy!" }'
Good Boy!
以固定宽度打印(左对齐)
当输入字符串小于指定的字符数,并且您希望它左对齐(通过在右侧补充空格)时,请在 %
后面和数字之前立即使用减号 (-
)。
"%6s"
右对齐,如下所示:
$ awk 'BEGIN { printf "|%6s|\n", "Good" }'
| Good|
"%-6s"
左对齐,如下所示:
$ awk 'BEGIN { printf "|%-6s|\n", "Good" }'
|Good |
打印美元符
要在价格值之前添加美元符号,只需在 printf
中的标识符之前添加美元符号,如下所示。
$ cat printf-width2.awk
BEGIN {
FS=","
printf "%-3s\t%-10s\t%-10s\t%-5s\t%-3s\n","Num","Description","Type","Price","Qty"
printf "-----------------------------------------------------\n"
}
{
printf "%-3d\t%-10s\t%-10s\t$%-.2f\t%-d\n",$1,$2,$3,$4,$5
}
$ awk -f printf-width2.awk items.txt
Num Description Type Price Qty
-----------------------------------------------------
101 HD Camcorder Video $210.00 10
102 Refrigerator Appliance $850.00 2
103 MP3 Player Audio $270.00 15
104 Tennis Racket Sports $190.00 20
105 Laser Printer Office $475.00 5
打印时带前导零
默认情况下,值右对齐,并在左侧添加空格。
$ awk 'BEGIN { printf "|%5s|\n", "100" }'
| 100|
对于右对齐且数字前面有 0
(而不是空格),请在数字前添加零 (0
)。 即使用 "%05s"``` 作为格式标识符,而不是
"%5s"```。
$ awk 'BEGIN { printf "|%05s|\n", "100" }'
|00100|
以下示例对数量字段使用前导零格式标识符。
$ cat printf-width3.awk
BEGIN {
FS=","
printf "%-3s\t%-10s\t%-10s\t%-5s\t%-3s\n","Num","Description","Type","Price","Qty"
printf "-----------------------------------------------------\n"
}
{
printf "%-3d\t%-10s\t%-10s\t$%-.2f\t%03d\n",$1,$2,$3,$4,$5
}
$ awk -f printf-width3.awk items.txt
Num Description Type Price Qty
-----------------------------------------------------
101 HD Camcorder Video $210.00 010
102 Refrigerator Appliance $850.00 002
103 MP3 Player Audio $270.00 015
104 Tennis Racket Sports $190.00 020
105 Laser Printer Office $475.00 005
打印绝对固定宽度字符串值
正如我们已经向您展示的,当输入字符串包含的字符多于格式说明符中指定的字符时,它会打印整个内容,如下所示。
$ awk 'BEGIN { printf "%6s\n", "Good Boy!" }'
Good Boy!
要打印最多 6 个字符,请在数字前添加小数点。即,使用 "%.6s"
代替 "%6s"
,即使输入字符串比下面所示的长度长,它也只会打印输入字符串中的 6 个字符。
$ awk 'BEGIN { printf "%.6s\n", "Good Boy!" }'
Good B
上述内容并不适用于 awk 的所有版本。在 GAWK 3.1.5 上它有效。 但在 GAWK 3.1.7 上它不起作用。
因此,打印固定字符的可靠方法可能是使用 substr
函数,如下所示。
$ awk 'BEGIN { printf "%6s\n", substr("Good Boy!",1,6) }'
Good B
点精确 (.
)
格式标识符中数字前面的点表示精度。
以下示例显示了数字格式标识符的数字前的点的工作原理。
此示例显示了使用 using .1
和 .4
(使用 d
、e
、f
和 g
格式说明符)时如何以不同方式打印数字 "101.23"
。
$ cat dot.awk
BEGIN {
print "----Using .1----"
printf ".1d--> %.1d\n", 101.23
printf ".1e--> %.1e\n", 101.23
printf ".1f--> %.1f\n", 101.23
printf ".1g--> %.1g\n", 101.23
print "----Using .4----"
printf ".4d--> %.4d\n", 101.23
printf ".4e--> %.4e\n", 101.23
printf ".4f--> %.4f\n", 101.23
printf ".4g--> %.4g\n", 101.23
}
$ awk -f dot.awk
----Using .1----
.1d--> 101
.1e--> 1.0e+02
.1f--> 101.2
.1g--> 1e+02
----Using .4----
.4d--> 0101
.4e--> 1.0123e+02
.4f--> 101.2300
.4g--> 101.2
打印报告到文件
您可以将 print
语句的输出重定向到 awk 脚本内的特定输出文件。
在以下示例中,第一个打印语句具有 ">report.txt"
,它创建 report.txt
文件并将打印语句的输出发送给该文件。
所有后续打印语句都有 ">>report.txt"
,它将输出附加到现有的 report.txt
文件中。
$ cat printf-width4.awk
BEGIN {
FS=","
printf "%-3s\t%-10s\t%-10s\t%-5s\t%-3s\n","Num","Description","Type","Price","Qty" > "report.txt"
printf "-----------------------------------------------------\n" >> "report.txt"
}
{
if ($5 > 10)
printf "%-3d\t%-10s\t%-10s\t$%-.2f\t%03d\n",$1,$2,$3,$4,$5 >> "report.txt"
}
$ awk -f printf-width4.awk items.txt
$ cat report.txt
Num Description Type Price Qty
-----------------------------------------------------
103 MP3 Player Audio $270.00 015
104 Tennis Racket Sports $190.00 020
另一种方法是在打印语句中不指定 ">report.txt"
或 ">>report.txt"
。
相反,在执行 awk 脚本时,将输出重定向到 report.txt
,如下所示。
$ cat printf-width5.awk
BEGIN {
FS=","
printf "%-3s\t%-10s\t%-10s\t%-5s\t%-3s\n","Num","Description","Type","Price","Qty"
printf "-----------------------------------------------------\n"
}
{
if ($5 > 10)
printf "%-3d\t%-10s\t%-10s\t$%-.2f\t%03d\n",$1,$2,$3,$4,$5
}
$ awk -f printf-width5.awk items.txt > report.txt
$ cat report.txt
Num Description Type Price Qty
-----------------------------------------------------
103 MP3 Player Audio $270.00 015
104 Tennis Racket Sports $190.00 020