基本功能
逐行处理文本:awk
会逐行读取输入文件(或标准输入),并对每一行进行处理。
字段分割:默认以空格或制表符分隔每一行的字段,可以通过 -F
选项指定其他分隔符。
模式匹配:可以根据正则表达式或条件匹配特定行。
数据操作:支持对字段进行数学运算、字符串操作和格式化输出。
awk的基本用法
1)基本操作方法
格式1:awk [选项] '[条件]{指令}' 文件
格式2:前置指令 | awk [选项] '[条件]{指令}'
其中,print 是最常用的编辑指令;若有多条编辑指令,可用分号分隔。
Awk过滤数据时支持仅打印某一列,如第2列、第5列等。
处理文本时,默认将空格、制表符作为分隔符。
条件可以用/ /的方式,与sed类似
[root@sv7 ~]# vim abc.txt
hello the world
ni hao ma
12:00 2088-9-04[root@sv7 ~]# awk '{print}' abc.txt #输出所有数据
[root@sv7 ~]# awk '/the/{print}' abc.txt #输出有the的那行
[root@sv7 ~]# awk '/the/{print $1}' abc.txt #输出有the的那行的第1列
[root@sv7 ~]# awk '/the/{print $1,$3}' abc.txt #输出有the的那行的第1,3列
[root@sv7 ~]# awk '{print $0}' abc.txt #输出所有行所有列
[root@sv7 ~]# awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
[root@sv7 ~]# awk '{print NR}' abc.txt #输出所有行的行号
[root@sv7 ~]# awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
[root@sv7 ~]# awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)再使用之前的user文档测试
[root@sv7 ~]# awk '/^root/{print NR}' user #找以root开头的行,显示该行的行号
[root@sv7 ~]# awk '/^root/{print NR,$0}' user #找以root开头的行,显示该行的行号,所有列
[root@sv7 ~]# awk '{print NF}' user #输出所有行的列号(每行有几列)2)选项 -F 可指定分隔符
[root@sv7 ~]# awk -F: '{print $1}' user #文档中如果没有空格,可以用F修改分隔符
[root@sv7 ~]# awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列awk还识别多种单个的字符,比如以“:”或“/”分隔
[root@sv7 ~]# awk -F [:/] '/^root/{print $1,$10}' userawk的print指令不仅可以打印变量,还可以打印常量
[root@sv7 ~]# awk -F: '{print $1" 的家目录是 "$6}' user #输出常量,加双引号即可
[root@sv7 ~]# awk -F: '{print $1" 的解释器是 "$7}' user利用awk提取本机系统数据
1)收集根分区剩余容量
[root@sv7 ~]# df -h | awk '/\/$/{print $4}' #使用df -h 作为前置指令交给awk处理找到以/结尾的行,并输出第4列
[root@sv7 ~]# df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出2)收集网卡流量信息
RX为接收的数据量,TX为发送的数据量。packets以数据包的数量为单位,bytes以字节为单位:
[root@sv7 ~]# ifconfig eth0 | awk '/RX p/{print "eth0网卡接收的数据量是"$5"字节"}'
[root@sv7 ~]# ifconfig eth0 | awk '/TX p/{print "eth0网卡发送的数据量是"$5"字节"}'格式化输出信息
1)awk处理的时机
awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行之后做一些总结性质的工作。在命令格式上分别体现如下:
awk [选项] '[条件]{指令}' 文件
awk [选项] 'BEGIN{指令} {指令} END{指令}' 文件BEGIN{ } 行前处理,读取文件内容前执行,指令执行1次{ } 逐行处理,读取文件过程中执行,指令执行n次END{ } 行后处理,读取文件结束后执行,指令执行1次格式化输出/etc/passwd文件
要求: 格式化输出passwd文件内容时,要求第一行为列表标题,中间打印用户的名称、UID、家目录信息,最后一行提示一共已处理文本的总行数,效果如图所示:
[root@sv7 ~]# awk -F: '{print "用户名:",$1, "UID是:",$3}' /etc/passwd
用户名: root UID是: 0
用户名: bin UID是: 1
用户名: daemon UID是: 2[root@sv7 ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6} END{print "系统中 有:"NR,"个用户"}' /etc/passwd
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin
...
系统中有: 33 个用户
此时结果已经显示,但是格式没有对齐,不太好看,可以使用column -t 调整一下排版
[root@sv7 ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6} END{print "系统中 有:",NR,"个用户"}' /etc/passwd | column -t
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin
awk处理条件
认识awk处理条件的设置
1)使用正则设置条件
/正则/ ~ 包含 !~不包含
[root@sv7 ~]# cat /etc/passwd > user #准备素材文件
[root@sv7 ~]# awk '/root/{print}' user #找含有root的行打印
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin[root@sv7 ~]# awk -F: '$1~/root/{print}' user #输出第1列包含root的行
root:x:0:0:root:/root:/bin/bash
[root@sv7 ~]# awk -F: '$7~/bash/{print}' user #输出第7列包含bash的行
[root@sv7 ~]# awk -F: '$7!~/bash/{print}' user #输出第7列不包含bash的行2)使用数值/字符串比较设置条件
比较符号:==(等于) !=(不等于) >(大于)
\>=(大于等于) <(小于) <=(小于等于)
[root@sv7 ~]# awk -F: '$1=="root"{print}' user #精准匹配第1列是root的行[root@sv7 ~]# awk -F: '$3==3{print}' user #输出第3列uid是3的行
[root@sv7 ~]# awk -F: '$3>=1000{print}' user #输出第3列uid大于等于1000的行
[root@sv7 ~]# awk -F: 'NR==2{print}' user #输出第2行,NR是行号
[root@sv7 ~]# awk -F: 'NR>20{print}' user #输出行号大于20的行3)逻辑测试条件;&&并且;||或者
[root@sv7 ~]# awk -F: '$3>10&&$3<15{print}' user #找第3列uid大于10 小于15的行
[root@sv7 ~]# awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行4)数学运算,BEGIN可以单独使用,不依赖于文件,后面可以不跟文件名
[root@sv7 ~]# awk 'BEGIN{print 1.5+2}'
3.5
[root@sv7 ~]# awk 'BEGIN{print 3*3}'
9
[root@sv7 ~]# awk 'BEGIN{print 12/3}'
4
[root@sv7 ~]# awk 'BEGIN{print 12-3}'
9
[root@sv7 ~]# awk 'BEGIN{print 11%3}'
2
[root@sv7 ~]# awk 'NR%2==0{print NR,$0}' user #在条件中使用运算,找到将行号除以2余数等于0的行,然后输出该行的行号和所有列,相当于输出偶数行
awk数组
awk数组
1)数组的语法格式
数组是一个可以存储多个值的变量,具体使用的格式如下:
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
[root@sv7 ~]# awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}' #使用awk测试数组,创建数组a,下标1对应值是10,下标2对应值是20,然后输出下标是2与下标是1的值注意:awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号:
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";print a["xyz"]}' 此时打印出的值只有一个,如果想要把所有的值打印还需要再次写上a["abc"],如果值特别多就不方便,那么可以使用循环解决问题
for(变量名 in 数组名){print 变量名} #这个格式可以查看数组的所有下标
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print i}}' #此时取的是a的下标,如果想要取值可以使用下面命令
abc
xyz
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print a[i]}}'
tom
jim也可以加上i把下标和值打印出来
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print i,a[i]}}'
abc tom
xyz jim