awk 命令详解
awk 是一种编程语言,用于在linux/nuix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大的编程工具。它在命令行中使用,但更多是作为脚本来使用。
awk 的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个恩,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
awk命令两种使用方式:
(1)命令行模式:awk [options] \'commands\' file(s)
(2)脚本模式:awk [options] -f file file[s]
awk 命令模式
awk [options] \'commands\' file(s) option: -F 定义字段分割符号 -v 定义变量并赋值 command: 1、范围说明或者正则表达式或者{awk命令语句1;awk命令语句2;} 2、范围说明部分可以是BEGIN、END、逻辑表达式或者为空 3、awk命令语句间用分号间隔 4、引用shell变量时需要用双引号引起,命令模式都在单引号\'\'里面 BEGIN{} {} END{} 行处理前 行处理 行处理后 命令格式: awk \'pattern\' filename 示例:awk \'/root/\' /etc/passwd awk \'{action}\' filename 示例:awk -F: \'{print $1}\' /etc/passwd awk \'pattern {action}\' filename 示例:awk -F: \'/root/{print $1,$3}\' /etc/passwd
示例:awk \'BEGIN{FS=\":\"} /root/{print $1,$3}\' /etc/passwd command |awk \'pattern {action}\' 示例:df -P | grep \'/\' |awk \'$4 > 25000 {print $4}\'
字段分割及相关变量
$1,$2,$3...$n:awk中用该顺序形式表示files中每行以间隔符号分割的各列的不同字段 $0 表示文本本身 NF 表示当前记录的字段数(列数) $NF 最后一列 $(NF-1) 倒数第二列 FNR/NR 行号 FILENAME 文件名 \"\\t\" 制表符 RS 换行符 \"\" 打印字符串 FS 定义间隔符 ~ 匹配,与==相比不是精确比较 !~ 不匹配,不精确比较 == 等于,必须全部相等,精确比较 /[0-9][0-9]+/ 两个或两个以上数字 -F\'[:#/]\' 定义三个分隔符
# awk -F: \'{print $0}\' /etc/passwd //打印文件所有内容 # awk -F: \'{print NR, $0}\' /etc/passwd /etc/hosts //打印文件所有内容,并包括行号 # awk -F: \'{print FNR,$0}\' /etc/passwd /etc/hosts # awk -F: \'{print $0,NF}\' /etc/passwd //保留记录的字段数 # awk \'BEGIN{FS=\":\"}{print $1,$3}\' /etc/passwd //输入字段分隔符,默认为空格
格式化输出:
print函数 # date |awk \'{print \"Month: \"$2 \"\\nYear: \"$NF}\' # awk -F: \'{print \"username is: \" $1 \"\\t uid is: \"$3}\' /etc/passwd # awk -F: \'{print \"\\tusername and uid: \" $1,$3 \"!\"}\' /etc/passwd # head -5 /etc/passwd|awk -F: \'BEGIN {print \"user\\thomedir\\tshell\"RS\"***********************\"};{print $1\"\\t\"$(NF-1)\"\\t\"$NF};END {print\"************END************\"}
print函数 # date |awk \'{print \"Month: \"$2 \"\\nYear: \"$NF}\' # awk -F: \'{print \"username is: \" $1 \"\\t uid is: \"$3}\' /etc/passwd # awk -F: \'{print \"\\tusername and uid: \" $1,$3 \"!\"}\' /etc/passwd 参数说明: %s 字符类型 %d 数值类型 占15字符 - 表示左对齐,默认是右对齐 printf默认不会在行尾自动换行,加\\n
awk模式和动作
任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。
模式可以是:正则表达式、比较表达式、条件表达式、算术运算符、逻辑操作符和复合模式、范围模式等。
正则表达式:
匹配记录(整行): # awk \'/^alice/\' /etc/passwd # awk \'!/root/\' passwd 匹配字段:匹配操作符(~ !~) # awk -F: \'$1 ~ /^admin/\' /etc/passwd # awk -F: \'$NF !~ /nologin$/\' /etc/passwd
比较表达式:
比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。
运算符 含义 示例 < 小于 x<y <= 小于或等于 x<=y == 等于 x==y != 不等于 x!=y >= 大于等于 x>=y > 大于 x>y
# awk -F: \'$3 == 0\' /etc/passwd # awk -F: \'$3 < 10\' /etc/passwd # awk -F: \'$7 == \"/bin/bash\"\' /etc/passwd # awk -F: \'$1 == \"root\" \' /etc/passwd # awk -F: \'$1 ~ /admin/ \' /etc/passwd # df -P | grep \'/\' |awk \'$4 > 25000\'
条件表达式:
# awk -F: \'$3>300 {print $0}\' /etc/passwd # awk -F: \'{ if($3>300) print $0 }\' /etc/passwd # awk -F: \'{ if($3>300) {print $0} }\' /etc/passwd # awk -F: \'{ if($3>300) {print $3} else{print $1} }\' /etc/passwd
算术运算:+ - * / %(模) ^(幂2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算 # awk -F: \'$3 * 10 > 500\' /etc/passwd
逻辑操作符和复合模式:
&& 逻辑与 a&&b || 逻辑或 a||b ! 逻辑非 !a
# awk -F: \'$3 > 50 && $3 <=100\' /etc/passwd # awk -F: \'$3 == 0 || $3 <=10\' /etc/passwd # awk -F: \'!($3 == 0 || $3 <=10)\' /etc/passwd
awk 脚本编程
条件判断:
if语句:
//格式 {if(表达式){语句;语句;...}} # awk -F: \'{if($3==0) {print $1 \" is administrator.\"}}\' /etc/passwd # awk -F: \'{if($3>0 && $3<1000){count++;}} END{print count}\' /etc/passwd //统计系统用户数
if...else语句:
//格式 {if(表达式){语句;语句;...}else{语句;语句;...}} # awk -F: \'{if($3==0){print $1} else {print $7}}\' /etc/passwd # awk -F: \'{if($3==0){count++} else{i++}} END{print \"管理员个数: \"count ; print \"系统用户数: \"i}\' /etc/passwd
if...else if...else语句:
//格式 {if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}} # awk -F: \'{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}\' /etc/passwd # awk -F: \'{if($3==0){i++} else if($3>999){k++} else{j++}} END{print \"管理员个数: \"i; print \" 普通用个数: \"k; print \"系统用户: \"j}\' /etc/passwd
循环:
while:
# awk \'BEGIN{i=1; while(i<=10){print i; i++} }\' # awk -F: \'{i=1; while(i<=10) {print $0; i++}}\' /etc/passwd //将每行打印10次
for:
# awk \'BEGIN{for(i=1;i<=5;i++){print i} }\' //C风格for awk -F: \'{for(i=1;i<=10;i++) print $0}\' /etc/passwd //将每行打印10次
数组:
# awk -F: \'{username[++i]=$1} END{print username[1]}\' /etc/passwd root # awk -F: \'{username[i++]=$1} END{print username[1]}\' /etc/passwd bin # awk -F: \'{username[i++]=$1} END{print username[0]}\' /etc/passwd root
数组遍历:
# awk -F: \'{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}\' /etc/passwd # awk -F: \'{username[++x]=$1} END{for(i=1;i<=x;i++) print i,username[i]}\' /etc/passwd # awk -F: \'{username[x++]=$1} END{for(i in username) {print i,username[i]} }\' /etc/passwd # awk -F: \'{username[++x]=$1} END{for(i in username) {print i,username[i]} }\' /etc/passwd
练习
1. 统计/etc/passwd 中各种类型shell的数量 # awk -F: \'{shells[$NF]++}END{ for(i in shells){print i,shells[i]}}\' /etc/passwd 2. 网站访问状态统计 <当前时实状态 netstat> # netstat -ant |grep :80 |awk \'{access_stat[$NF]++}END{for(i in access_stat){print i, access_stat[i]}}\' # netstat -ant |grep :80 |awk \'{access_stat[$NF]++} END{for(i in access_stat ){print i,access_stat[i]}}\' |sort -k2 -n |head # ss -an |grep :80 |awk \'{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}\' # ss -an |grep :80 |awk \'{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}\' |sort -k2 -rn 3. 统计当前访问的每个IP的数量 <当前时实状态 netstat,ss> # ss -an |grep :80 |awk -F\":\" \'!/LISTEN/{ip_count[$(NF-1)]++} END{for(i in ip_count){print i,ip_count[i]}}\' |sort -k2 -rn 4. 统计Apache/Nginx日志中某一天的PV量 <统计日志> # grep \'07/Aug/2012\' access.log |wc -l 5. 统计Apache/Nginx日志中某一天不同IP的访问量 <统计日志> # grep \'07/Dec/2018\' access.log |awk \'{ips[$1]++} END{for(i in ips){print i,ips[i]} }\' |sort -k2 -rn # grep \'07/Dec/2018\' access.log |awk \'{ips[$1]++} END{for(i in ips){print i,ips[i]} }\' |awk \'$2>100\' |sort -k2 6. awk函数 统计用户名为4个字符的用户 # awk -F: \'$1~/^....$/{count++; print $1} END{print \"count is: \" count}\' /etc/passwd # awk -F: \'length($1)==4{count++; print $1} END{print \"count is: \"count}\' /etc/passwd 7. 取得网卡IP(除ipv6以外的所有IP) # ifconfig |awk \'/[ ]inet[ ]/{print $2}\' 8. 获得内存使用情况 # free -m |awk \'NR==2{print $3*100/$2}\' 9. 获得磁盘使用情况 # df |awk \'/\\/$/{print $5}\' 10. 清空本机的ARP缓存 # arp |awk \'!/Address/{print \"arp -d \" $1}\'|bash # arp -n |awk \'/^[0-9]/{print $1}\' |xargs -I {} arp -d {}
继续阅读与本文标签相同的文章
-
阿里云上云企业案例周刊·第1期
2026-05-19栏目: 教程
-
CC攻击有哪些特点以及如何防御CC攻击?
2026-05-19栏目: 教程
-
Generator函数
2026-05-19栏目: 教程
-
陈淮:美好生活、城市化与房地产怎样改变了中国
2026-05-19栏目: 教程
-
菜鸟物流张春晖:只有重构旧要素创造新要素,物流才能成为真正意义上的社会基础设施。
2026-05-19栏目: 教程
