一.什么是awk,nawk,gawk?
awk是一种用于处理数据和生成报表的UNIX编程语言。nawk是awk的新版本。gawk是基于linux的GNU版本。
二.awk的格式
awk程序是由awk命令,括在括号(或写在文件)中的程序指令以及输入文件的文件名几个部分组成。如果没有指定输入文件,输入则来自标准输入。
awk指令由模式、操作或模式与操作的组合组成。
awk以逐行方式扫描文件(或输入),从第一行到最后一行,以查找匹配某个特定模式的文本行,并对这些文本行执行(括在括号中的)指定动作。如果只给出模式而未指定动作,则所有匹配模式的行都显示在屏幕上。如果只指定动作而未定义模式,会对所有输入行执行自动动作。
1.从文件输入
格式:
awk 'pattern' filename
awk '{action}' filename
awk 'pattern {action}' filename
下面的例子分别演示了这三种格式
cat test_awk.txt
abc def hic lmn abc
123 456 1.23 4.5 321
ABC Def hIc lmN ABC
ABC Def hIc lmN dsf
You are a good boy
That's a very lovely dog
例1:
awk '/ABC/' test_awk.txt #ABC Def hIc lmN ABC #ABC Def hIc lmN dsf
例2:
awk '{print $1}' test_awk.txt #abc #123 #ABC #ABC #You #That's
例3:
awk '/ABC/{print $1}' test_awk.txt #ABC #ABC
2.用于管道
格式:
command | awk 'pattern'
command | awk '{action}'
command | awk 'pattern {action}'
上面的例3,可以用下面的方式实现:
例4:
cat test_awk.txt | awk '/ABC/{print $1}' #ABC #ABC
例5:
cat /etc/passwd | awk '/root/' #root:x:0:0:root:/root:/bin/bash #operator:x:11:0:operator:/root:/sbin/nologin
三.awk的工作原理
请看下面的文件names:
cat names
Tom Savage 100
Molly Lee 200
John Don 300
使用下面的awk命令:
awk '{print $1, $3}' names
(1)awk使用一行作为输入(通过文件或者管道),并将这一行赋给内部变量$0,默认时每一行也可以成为一条记录,以换行符结束。
(2)然后行被空格分割成字段(单词),每个字段存储在已编号的变量中,从$1开始,可以多达100个字段。
(3)awk是如何知道空格是用来分割字段的呢?因为有另一个内部变量FS来确定字段的分隔符。初始时,FS被赋为空格——包含空格和制表符。如果需要指定其他的字符作为分隔符,如冒号或破折号,则需要将FS设置为新的分隔符。
(4)awk打印字段时,将以下面方式用print打印函数
{print $1, $3}
输出显示了每个字段时用的分隔符,如下所示:
Tom 100
Molly 200
John 300
awk在Tom和100之间加了空格,因为$1和$3之间存在一个逗号。逗号比较特殊,他被映射为另一个内部变量。成为输出字段分隔符(output filed separator, OFS),OFS默认为空格。逗号被OFS中存储的变量替换。
(5)awk输出之后,将从文件中获取另一行,并将其存储到$0中,覆盖掉原来的内容,然后将新的字符串分割成字段并进行处理。这个过程将持续到整个文件的所有行都处理完毕。
四.格式和输出
1.print函数
print函数的参数可以是变量,数值或字符串常量。字符串必须用双引号括起来,参数之间用逗号分割。
print函数的输出可以被重定向,也可以通过管道传给另一个程序。其他程序的输出也可以通过管道交给awk打印。
例1:
date | awk '{print "当前时间为:" $5}' #当前时间为:16:48:20
2.OFMT变量
打印数字时,可能需要控制数字的格式,这可以通过printf实现,但是也可以通过设置一个特殊的awk变量OFMT用print函数来实现。OFMT变量的默认值是:“%.6gd”,表示只打印小数部分的前六位。
例2
awk 'BEGIN{OFMT="%.2f";print 0.123456, 12E-2}' #0.12 0.12
3.printf函数
printf函数返回一个带格式的字符串给标准输出。如同C语言中的printf语句一样。
打印变量时输出所在的位置成为“域(filed)” ,域的宽度(width)是指该域中所包含的字符个数。
下面的例子中,printf控制的管道符(竖杠)是文本的部分,用于指示格式的起始和结束。
echo "test awk" | awk '{printf "|%-15s|\n", $1}' #|test | echo "test awk" | awk '{printf "|s|\n", $2}' #| awk| echo 80 | awk '{printf "|%-8d|\n", $1}' #|80 | echo 80 | awk '{printf "|%8d|\n", $1}' #| 80|
说明:%后面跟一个整数或一个负数表示打印字符串或数字的长度,符号表示左对齐。如上面的例子打印test的长度为15位,其中test占4位,后面的11位用空格补齐。