awk 格式化打印
awk中的printf命令允许您使用格式说明符打印格式化输出。
格式说明符的编写方式如下:
%[modifier]control-letter
可用于printf的格式说明符:
c将数字输出打印为字符串。
d打印整数值。
e打印科学号码。
f打印浮点值。
o打印八进制值。
s打印文本字符串。
使用printf来格式化我们的输出:
$ awk 'BEGIN{ x = 100 * 100 printf "The result is: %e\n", x }'
特定AWK命令或者GNU AWK为文本处理提供了一种脚本语言。
使用awk脚本语言,我们可以进行以下操作:
- 定义变量。
- 使用字符串和算术运算符。
- 使用控制流程和循环。
- 生成格式化的报告。
其他awk变量
还有一些其他变量可以获取更多信息:
ARGC 获取传递参数的数量。
ARGV 获取命令行参数。
ENVIRON shell环境变量和相应值的数组。
FILENAME 由awk处理的文件名。
NF 正在处理的行的字段数。
NR 处理的记录总数
FNR 正在处理的记录
IGNORECASE 忽略大小写
让我们看一些示例:
$ awk 'BEGIN{print ARGC,ARGV[1]}' myfile
ENVIRON变量 可以查看shell环境变量,如下所示:
$ awk ' BEGIN{ print ENVIRON["PATH"] }'
可以在不使用ENVIRON变量的情况下使用bash变量,如下所示:
$ echo | awk -v home=$HOME '{print "My home is " home}'
NF变量指定记录中的最后一个字段,不需要知道其位置:
$ awk 'BEGIN{FS=":"; OFS=":"} {print ,$NF}' /etc/passwd
如果这样写:$NF, NF变量可用作数据字段变量。
让我们看两个例子,来了解FNR和NR变量之间的区别:
$ awk 'BEGIN{FS=","}{print ,"FNR="FNR}' myfile myfile
在此示例中,AWK命令定义了两个输入文件。
同一个文件,但处理了两次。
输出是第一个字段值和FNR变量。
现在,换成NR变量并查看不同:
$ awk ' BEGIN {FS=","} {print ,"FNR="FNR,"NR="NR} END{print "Total",NR,"processed lines"}' myfile myfile
FNR变量在第二个文件时变为1,但NR变量会保持其值。
awk预处理
如果我们需要在输出结果中创建标题,
我们可以使用Begin关键字来实现此功能。
它将在处理数据之前运行:
$ awk 'BEGIN {print "Report Title"}'
示例:
$ awk 'BEGIN {print "The File Contents:"} {print10 15 6 33 45}' myfile
awk结构化命令
awk 条件语句
AWK脚本语言支持if 条件语句。
testfile包含以下内容:
$ awk '{if ( > 30) print }' testfile
找出大于30的记录
$ awk '{ if ( > 30) { x = * 3 print x } }' testfile
就是这么简单。
如果要运行多个语句,则应使用括号:
$ awk '{ if ( > 30) { x = * 3 print x } else { x = / 2 print x }}' testfile
我们可以这样使用else语句:
$awk '{if ( > 20) print *2;else print /2 ' testfile
或者在同一行中(if语句后面使用分号)
$ cat myfile 124 127 130 112 142 135 175 158 245 118 231 147
awk while循环
我们可以使用while循环来迭代数据。
测试数据文件:
$ awk '{ sum = 0 i = 1 while (i < 5) { sum += $i i++ } average = sum / 3 print "Average:",average }' testfile
awk while循环示例:
$ awk '{ tot = 0 i = 1 while (i < 5) { tot += $i if (i == 3) break i++ } average = tot / 3 print "Average is:",average }' testfile
我们可以使用break命令提前退出循环:
$ awk '{ total = 0 for (var = 1; var < 5; var++) { total += $var } avg = total / 3 print "Average:",avg }' testfile
awk for循环
awk脚本语言也支持for 循环:
$ echo "Hello Tom" | awk '{="Adam"; printHello Adam}'
在awk中执行多个命令
要运行多个命令,请使用像这样的分号分隔:
$ awk options program file
第一个命令使$2字段 等于 Adam。
第二个命令打印整行。
输出:
$ awk 'BEGIN{x=exp(5); print x}'
awk选项
awk命令语法
$ awk '{print }' myfile
Awk 可以使用的选项有:
-f fs 指定文件分隔符。
-f file指定包含awk脚本的文件。
-v var = value声明变量。
awk 内置函数
Awk提供了几种内置的函数,例如:
数学函数
我们可以在AWK脚本中使用这些数学函数:
sin(x) | cos(x) | sqrt(x) | exp(x) |log(x) | rand()
$ awk -F: '{print }' /etc/passwd
使用awk变量
使用awk,我们可以处理文本文件。
awk为找到的每个数据字段分配一些变量:
- $0 整行
- $1 第一字段
- $2 第一字段
- $n 第n字段
空白字符(空格或者tab制表符)在awk中用于字段之间的默认分隔符。
查看下面的示例,看awk是如何处理的。
$ awk 'BEGIN{x = "onitroad"; print toupper(x)}'
上面的示例将打印每行的第一个单词(字段)。
有时某些文件中的分隔符不是空格,而是其他字符。
这时我们可以使用-F选项指定它:
$ awk 'BEGIN {print "The File Contents:"} {printBEGIN { print "用户及其对应Home路径:" print " UserName \t HomePath" print "___________ \t __________" FS=":" } { print " \t " } END { print "The end" }} END {print "File footer"}' myfile
此命令打印在passwd文件中的第一个字段。
我们使用冒号作为分隔符。
字符串函数
有许多字符串函数,例如:
$ awk -f myscript /etc/passwd
查看手册获取根据其他函数。
Awk后处理
要在处理数据后运行脚本,请使用END关键字:
{print " home at " }
这很有用,我们可以使用它来添加一个页脚。
示例:
myscript
$ awk -F: -f testfile /etc/passwd
执行:
{ text = " home at " print text }
从文件中读取awk脚本
我们可以输入来自文件的AWK脚本,使用-f选项指定该文件。
假设testfile文件包含以下脚本内容:
$ awk -F: -f testfile /etc/passwd
执行脚本:
root home at /root onitroad home at /oir apache home at /var/www
脚本还可以这样写:
$ awk 'BEGIN{FS=":"; OFS="-"} {print ,,}' /etc/passwd
1235.96521 927-8.3652 36257.8157
输出:
$ awk 'BEGIN{FIELDWIDTHS="3 4 3"}{print ,,}' testfile
awk内置变量
我们刚才看到了数据字段变量$ 1,2 $ 3用于提取数据字段,还有字段分隔符变量FS。
除此之外,还有其他的内置变量。
以下列表显示了awk中一些内置变量:
FIELDWIDTHS 指定字段宽度。
RS 指定记录分隔符。
FS 指定字段分隔符。
OFS 指定输出分隔符。
ORS 指定输出分隔符。
默认情况下,OFS变量是空格,我们可以设置OFS变量以指定所需的分隔符:
123 5.9 6521 927 -8.3 652 362 57.8 157
有时,字段间没有固定的分隔符。在这些情况下,可以使用FIELDWIDTHS变量来解决这个问题。
假设我们有这个内容:
Person Name 123 High Street (222) 466-1234 Another person 487 High Street (523) 643-8754
$ awk 'BEGIN{FS="\n"; RS=""} {print ,}' addresses
根据字段的宽度进行分割。
输出:
$ awk ' BEGIN{ test="Welcome to onitroad website" print test }'
如果数据在不同的行:
$ awk '{print "Welcome to awk command tutorial "}'
在上面的示例中,AWK无法正确处理字段,因为该字段由换行符而不是空格分隔。
我们需要将FS设置为换行符,RS设置为空白文本。这样空白行将当做分隔符:
$ awk ' function myfunc() { printf "The user %s has home path at %s\n", , } BEGIN{FS=":"} { myfunc() }' /etc/passwd
awk用户定义的变量
变量名称可能是任何字符,但它不能以数字开头。
我们可以将变量分配为shell脚本中的变量,像这样:
##代码##awk脚本
要定义AWK脚本,使用由单引号包围的大括号,如下所示:
##代码##要终止程序,请按Ctrl + D。
awk用户定义的函数
我们可以自己定义函数,如下所示:
##代码##我们定义了一个名为myprint的函数,然后我们在脚本中使用它来打印输出。