AWK
awk 常用选项与参数
Option
Description
-F
指定分隔符
awk常用的内置变量
Variable
Description
FILENAME
当前输入文件名,若有多个文件,则只表示第一个。如果输入是来自标准输入,则为空字符串
$0
当前记录的内容
$N
N表示字段号,最大值为NF变量的值
FS
字段分隔符,由正则表达式表示,默认为" "空格
RS
输入记录分隔符(换行符),默认为"\n",即一行为一个记录
NF
当前记录字段数
NR
已经读入的记录数
FNR
当前输入文件的记录数,请注意它与NR的区别
OFS
输出字段分隔符,默认为" "空格
ORS
输出记录分隔符,默认为"\n"
简单案例
awk -F ":" '{print NR,$1,$NF}' test.txt
# 打印test.txt文件内容中以:分隔后的第一列和最后一列并显示行号awk 'NR==2,NR==3' test.txt
# 打印test.txt文件内容中第2行与第3行的内容awk 'NR>1,NR<4' test.txt
# 打印test.txt文件内容中第2行与第3行的内容awk 'NR==2{print $2}' test.txt
# 打印test.txt文件内容中第2行第2列的内容# 查看本机正在使用的端口并排序显示
netstat -lntup | awk 'NR>2 {print $4}' | awk -F ":" '{print $NF}' | sort -n | uniq | nl常用过滤
过滤行
过滤 /etc/passwd 中含有字符串 "nologin" 且行号大于 20 的行
awk -F ':' '/nologin/ && NR>=20' /etc/passwd
# 输出
awk -F ':' '/nologin/ && NR>=20 {print $1,$NF}' /etc/passwd | column -t
nscd /sbin/nologin
tcpdump /sbin/nologin
rpc /sbin/nologin
rpcuser /sbin/nologin
nfsnobody /sbin/nologin
nginx /sbin/nologin过滤列
过滤 /etc/passwd 中第三列小于10的行
awk -F ':' '$3<10' /etc/passwd
# 输出
awk -F ':' '$3<10' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin过滤 /etc/passwd 中第四列以0或1开头和结尾的行
awk -F ':' '$4 ~ /^[01]$/ {print $1,$4,$NF}' /etc/passwd | column -t
# 输出
awk -F ':' '$4 ~ /^[01]$/ {print $1,$4,$NF}' /etc/passwd | column -t
root 0 /bin/bash
bin 1 /sbin/nologin
sync 0 /bin/sync
shutdown 0 /sbin/shutdown
halt 0 /sbin/halt
operator 0 /sbin/nologin
awk -F ':' '$4 ~ /^[01]+$/ {print $1,$4,$NF}' /etc/passwd | column -t
root 0 /bin/bash
bin 1 /sbin/nologin
sync 0 /bin/sync
shutdown 0 /sbin/shutdown
halt 0 /sbin/halt
operator 0 /sbin/nologin
games 100 /sbin/nologin统计
统计 /etc/passwd 行数
awk '{i++} END {print i}' /etc/passwd求和
seq 10 > num.txt
awk '{i+=$1} END {print i}' num.txt
# 输出
55AWK 和 SHELL 语法区别

演示文件(下方均使用此文件进行演示)
cat user.txt
user1 70 72 74 76 78 70
user2 80 82 84 86 88 80
user3 90 92 94 96 98 90
user4 60 62 64 66 68 60
user5 80 82 84 86 88 80if 判断
输出第二列大于80的行的第一列
awk '{if($2>=80) print $1}' user.txt
# 输出
user2
user3
user5awk '{if($2>=80) print $1,$2}' user.txt
# 输出
user2 80
user3 90
user5 80同时输出多个结果
awk '{if($2>=80) {print $1;print $2}}' user.txt
# 输出
user2
80
user3
90
user5
80for 循环
循环取列
head -1 user.txt | awk '{for(c=2;c<=NF;c++) print $c}'
# 输出
70
72
74
76
78
70循环求和
head -1 user.txt | awk '{for(c=2;c<=NF;c++) {sum+=$c; print sum}; print sum}'
# 输出
70
142
216
292
370
440
440head -1 user.txt | awk '{for(c=2;c<=NF;c++) sum+=$c; print sum}'
# 输出
440head -1 user.txt | awk '{for(c=2;c<=NF;c++) sum+=$c; print sum/6}'
head -1 user.txt | awk '{for(c=2;c<=NF;c++) sum+=$c; print sum/(NF-1)}'
# 输出
73.3333求每行数据的平均值
# 错误的用法,sum在处理每行时没清零,导致一直累加
awk '{for(c=2;c<=NF;c++) sum+=$c; print sum/(NF-1)}' user.txt
# 输出
73.3333
156.667
250
313.333
396.667# 正确的用法
awk '{sum=0; for(c=2;c<=NF;c++) sum+=$c; print sum/(NF-1)}' user.txt
# 输出
73.3333
83.3333
93.3333
63.3333
83.3333数组
求每行的平均值并输出
awk '{sum=0; for(column=2;column<=NF;column++) sum+=$column; average[$1]=sum/(NF-1)} END{for(user in average) print user,average[user]}' user.txt
# 输出
user1 73.3333
user2 83.3333
user3 93.3333
user4 63.3333
user5 83.3333求每行平均值的和
awk '{sum=0; for(column=2;column<=NF;column++) sum+=$column; average[$1]=sum/(NF-1)} END{for(user in average) sum2+=average[user]; print sum2}' user.txt
# 输出
396.667求每行平均值的平均值
awk '{sum=0; for(column=2;column<=NF;column++) sum+=$column; average[$1]=sum/(NF-1)} END{for(user in average) sum2+=average[user]; print sum2/NR}' user.txt
# 输出
79.3333脚本形式
cat avg.awk
{sum=0; for(column=2;column<=NF;column++) sum+=$column; average[$1]=sum/(NF-1)} END{for(user in average) sum2+=average[user]; print sum2/NR}
awk -f avg.awk user.txt
79.3333命令行参数数组 ARGC ARGV
ARGC 命令行参数个数
ARGV 每个参数的内容
cat arg.awk
BEGIN{
for(x=0;x<ARGC;x++)
print ARGV[x]
print ARGC
}
awk -f arg.awk 11 22 33
awk
11
22
33
4
生产案例
统计 nginx 日志中非 GET 和 POST 请求的个数
awk '!/GET|POST/ {i++} END{print i}' access.log统计 nginx 日志中 GET 和 POST 请求各个状态码出现的次数
awk '/GET|POST/ {array[$9]+=1} END{for(n in array) print n,array[n]}' access.log统计 nginx 日志中 GET 和 POST 请求各个状态码的流量
awk '/GET|POST/ {array[$9]+=$10} END{for(n in array) print n,array[n]}' access.logLast updated