简介
AWK是一个优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人阿尔佛雷德·艾侯、彼得·温伯格和布莱恩·柯林汉姓氏的首个字母)的最大功能取决于一个人所拥有的知识。awk经过改进生成的新的版本nawk,gawk,现在默认linux系统下日常使用的是gawk,用命令可以查看正在应用的awk的来源(ls -l /bin/awk )
一个简单的例子
#创建一个文件
vim awk.txt
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
字段解释: 姓名 每小时工资 工作时长
#打印每位员工的名字以及报酬
awk '$3>0 {print $1,$2*$3}' awk.txt
$3>0 是模式
print $1,$2*$3是动作
#想知道哪些员工在偷懒
awk '$3==0 {print $1}' awk.txt
执行结果图:
AWK程序结构
- AWK程序执行流程
awk的基本操作是在由输入行组成的序列中, 陆续地扫描每一行, 搜索可以被"模式"匹配(match) 的行.如果匹配则执行"动作",一直持续到所有的输入被读取完毕
- 模式-动作分析
(1)模式-动作都存在 awk '$3==0 {print $1}' awk.txt
(2)模式存在,动作不存在 awk '$3==0' awk.txt
(3)模式不存在,动作存在 awk '{print $1}' awk.txt
(4)不可以两者都不存在(不能够运行)
AWK命令的运行格式
#后面接文件
awk '$3==0 {print $1}' awk.txt 后面接一个文件
awk '$3==0 {print $1}' awk.txt awk02.txt 后面接两个文件
#等待输入
awk '$3==0 {print $1}' 后面不接任何文件,等待输入再去判断
#将awk程序放入文件中
cat program
$3==0 {print $1}
执行命令: awk -f program awk.txt
AWK的输出格式
- 数据类型
-
数字和字符串
- 行和字段
awk从它的输入中每次读取一行,将行分解为一个个的字段(默认将字段看作是非空白字符组成的序列).
当前输入行的第一个字段叫作$1,第二个是$2,依次类推,一整行记为$0,每行的字段数有可能不一样.
- 案例
#打印每一行
awk '{print}' awk.txt 或 awk '{print $0}' awk.txt
#打印某些字段
awk '{print $1,$3}' awk.txt
#打印每行的字段数量(内建变量NF)
awk '{print NF}' awk.txt
#打印第一个字段和最后一个字段
awk '{print $1,$NF}' awk.txt
#计算和打印
awk '{print $1,$2 * $3}' awk.txt
#打印行号(NR)
awk '{print NR,$0}' awk.txt
#拼接字符串和字段
awk '{print $1,"今天的收入是",$2 * $3}' awk.txt
#格式化输出
awk '{ printf("%s 今天的收入是 $%.2f\n",$1,$2*$3) }' awk.txt
固定宽度输出
awk '{ printf("%-8s 今天的收入是 $%6.2f\n",$1,$2*$3) }' awk.txt
输出排序
awk '{ printf("%6.2f,%-8s 今天的收入是 $%6.2f\n",$2*$3,$1,$2*$3) }' awk.txt |sort -nk3 -t,
AWK模式匹配
- 单模式
#每小时工资大于5的记录
awk '$2>5 {print $0}' awk.txt
#报酬超过50的员工
awk '$2*$3>50 {print $1,$2*$3}' awk.txt
#查询名字为Mark的记录
awk '$1=="Mark" {print $0}' awk.txt
#正则表达式匹配名字带有Mar的记录
awk '/Mar/ {print $0}' awk.txt
- 模式组合
#打印那些$2至少为4,或者$3至少为20的行
awk '$2>=4||$3>=20 {print $0}' awk.txt
awk '!($2<4&&$3<20) {print $0}' awk.txt
#打印那些$2至少为4,并且$3至少为20的行
awk '$2>=4 && $3>=20 {print $0}' awk.txt
- BEGIN 与 END
特殊的模式 BEGIN 在第一个输入文件的第一行之前被匹配, END 在最后一个输入文件的最后一行被处理之后匹配.
awk 'BEGIN {*********} END{***********}'
awk 'BEGIN {print "NAME RATE HOURS"} {print} END{print "END"}' awk.txt
awk 'BEGIN {print "NAME RATE HOURS";print "------"} {print} END{print "------";print "END"}' awk.txt
用AWK计算
- 计算总和
#工作时长超过15小时的员工总人数
awk '$3>15 {emp=emp+1} END{print emp,"工作时长超过15小时的员工人数"}' awk.txt
- 计算平均数
#计算员工的平均工资
awk '{pay=pay+$2*$3} END{print NR,"员工总人数";print "总工资",pay; print "平均工资",pay/NR}' awk.txt
- 查找最大值
#查找每小时工资最高的员工
awk '$2 >maxrate {maxrate=$2;maxemp=$1} END{print "每小时工资最高的员工是:",maxemp,"工资是:",maxrate}' awk.txt
- 打印最后一行
awk '{last=$0} END{print last}' awk.txt
字符串拼接
#name之间加一个空格
awk '{names=names $1 " "} END{print names}' awk.txt
内建函数
#length 求字符串长度
计算名字的长度
awk '{print $1,length($1)}' awk.txt
#计算文本的行数,总字段数,总字节数
awk '{nc=nc+length($0)+1;nw=nw+NF} END{print NR,"lines,",nw,"words,",nc,"characters"}' awk.txt
流程控制语句
- if-else语句
#查找每小时工资多于 $6.00 的雇员的总报酬与平均报酬
awk '$2>6 {n=n+1;pay=pay+$2*$3} END{if(n>0) print n,"employees,total pay is",pay,"average pay is",pay/n;else print "not exit"}' awk.txt
- while语句
计算1到100总和
awk 'BEGIN{ test=100; total=0; while(i<=test) { total+=i; i++; } print total; }' 5050
#shell脚本
#!/bin/bash
total=0
i=0
while [ $i -le 100 ]
do
let total+=$i
let i++
done
echo $total
- for语句
#计算1到100的总和
awk 'BEGIN{ total=0; for(i=0;i<=100;i++) { total+=i; } print total; }'
- 数组
#倒着打印每行记录
awk '{line[NR] = $0} END {i=NR; while (i>0){ print line[i];i=i-1}}' awk.txt
awk '{line[NR] = $0} END{for(i=NR;i>0;i--){print line[i]}}' awk.txt
AWK 生产案例
#输入的总行数
awk 'END{print NR}' awk.txt
#打印第2行
awk 'NR==2 {print $0}' awk.txt
#打印每行最后一个字段
awk '{print $NF}' awk.txt
#打印最后一行最后一个字段
awk '{field=$NF} END{print field}' awk.txt
#打印字段数多于 2 个的输入行
awk 'NF>2 {print $0}' awk.txt
#打印最后一个字段值大于 4 的输入行
awk '$NF>4{print $0}' awk.txt