定义
awk命令是由Aho, Kernighan和Weinberger编写的,因此得名awk。
是一门模式扫描和处理的语言。它也是一种语言,支持流控(if,while,do,for等),支持正则,数据运算等
工作原理
与sed命令一样, 均是一行一行的读取、处理
不同的是sed作用于一整行的处理, 而awk将一行分成数个字段来处理。其中$0代表整行文字,$1代表第1个字段,依次类推。
语法
1.完整语法如下:
awk ‘BEGIN{commands}pattern{commands}END{commands}’ filename
BEGIN语句块 在awk开始从输入流中读取行 之前 被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
END语句块 在awk从输入流中读取完所有的行 之后 即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。
pattern语句块 中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
BEGIN后面{}里面的命令是处理数据前的命令。END{}后面的命令是处理数据后执行的命令。这两个命令只会执行一次。
而pattern后面的命令是每一行文本都会执行的,相当于一个for循环遍历所有行,对每行都执行pattern后面{}的命令
[root@localhost ~]# awk -F: 'BEGIN{print"####start####"} /bash/{print $1,$3} END{print"###end###"} ' /etc/passwd
执行结果如下:
2.常用语法如下:
awk -F 分隔符 ‘/模式/ {动作}’ file
模式就是匹配的规则,用来查找和匹配文本内容的,动作是用来处理匹配内容的
注意:
1.没有动作,则默认是输出按模式匹配到的内容,和grep用法一样
2.只有动作,没有模式,则默认是对所有数据
3.若有多个动作,则动作之间要用";"分割
4.print动作是将文本输出到STDOUT(屏幕)
常用选项
-F
描述
-F:指定分隔符。分隔符分两种,如下:
1.输入分隔符(FS变量:filed separater) 。默认以空白(tab、回车和空格)作为分隔符
2.输出分隔符(OFS变量:output filed separater)
用法
1.指定输入分隔符是“:”,且输出分割符是#:
awk -F : 'OFS="#"{print $1,$2,$3}' /etc/passwd
awk -F : '{print $1"#"$2"#"$3}' /etc/passwd ##等价于上式
其中“,”的作用是代表OFS变量的值,相当于python里面指定输出 的格式。也可理解为python里面的占位符,只不过该占位符只代表OFS的值
2.指定分隔符可以是“:”,也可以是"/"
[root@localhost ~]# awk -F'[:/]' '{print $1,$3}' /etc/passwd
-v选项
描述
awk中用来引用外部shell变量等
用法
[root@localhost ~]# name="hxy"
[root@localhost ~]#cat /etc/passwd | awk -v new_name=$name -F: '$1 ~new_name {print $1,$3,$4}'
另外两种引用变量的方法:
使用双引号引用外部变量
[root@localhost check]# awk -F: " \$1 ~ /$name/ {print \$1,\$3,\$4}" /etc/passwd
3.在BEGIN里面定义变量
常用于自定义的变量,用于实现特定功能。
例如使用awk命令实现1+2+3+…+10的功能,并将结果输出
[root@localhost check]# watch -n 1 -d "ifconfig ens33|awk '/bytes/ {print $5}'"
awk的功能
文本截取
例如:获取etc/passwd文件中以a/b/c开头的内容的第1、3列
[root@localhost ~]# awk -F: '/^[abc]/{print $1,$3}' /etc/passwd
取/etc/passwd文件中的第5-19行:
##以下两种方法等价
[root@localhost ~]# awk 'NR==5,NR==9{print $0}' /etc/passwd
[root@localhost ~]# awk 'NR>=5 && NR<=9{print $0}' /etc/passwd
文本匹配
##模糊匹配
[root@localhost ~]# awk -F: '$1 ~ /hxy/ {print $1,$3}' /etc/passwd
##精确匹配
[root@localhost ~]# awk -F: '$1=="hxy" {print $1,$3}' /etc/passwd
小数的运算
shell里面只有整数的运算,若要用小数运算,需要用bc,bc用法如下:
[root@localhost ~]# echo 80+43.2 |bc
用awk进行小数的运算如下:
[root@localhost ~]# echo | awk '{print 80+54.2}'
例子
1.找出1-100之间能被5整除或者是以1开头的数字
[root@localhost ~]# seq 100|awk -F: '$1%5==0 || $1 ~ /^1/ {print $1,$3}'
2.统计文件行数
[root@localhost ~]# awk 'BEGIN{i=0} {i++} END{print i}' /etc/passwd
3.输出所有的用户名并显示在文件中的顺序
##两者等价
[root@localhost ~]# awk -F: 'BEGIN{i=0} {i++;print i,$1} END{print i}' /etc/passwd
[root@localhost ~]# awk -F: '{print NR,$1} ' /etc/passwd
4.统计用户名中包含a的,并且统计个数
[root@localhost ~]# awk -F: 'BEGIN{i=0} $1 ~ /a/{i++ ;print i,$1} END{print "总共行数"i}' /etc/passwd
5.使用NF变量显示passwd文件倒数第二列的内容
[root@localhost check]# awk -F: '{print $(NF-1)}' /etc/passwd
6.显示passwd文件中第7列不是bash的用户名
[root@localhost check]# awk -F: '$7 !~ /bash/ {print $1}' /etc/passwd
7.显示passwd文件中行号是5结尾的行号和行
[root@localhost check]# awk -F: 'NR ~ /5\>/ {print $0,NR}' /etc/passwd
8.用ip add 只显示ip(不能使用tr或者cut命令)
[root@localhost ~]# ip add | awk '/inet\>/ {print $2}'
9.使用awk显示ens33的入站流量和出站流量(字节) --》用ifconfig
[root@localhost ~]# ifconfig ens33|awk '/bytes/ {print $5}'
10.使用awk命令统计以r开头的用户数目
[root@localhost check]# awk -F: 'BEGIN{i=0} $1 ~/^r/ {i++;print $1} END{print "总共有"i"个用户以r开头"}' /etc/passwd
扩充
awk的内置变量
1.NR(number of record):代表当前处理的行号,初值为0
2.FS:输入分隔符,默认是空白
3.OFS:输出分隔符,默认是一个空格
4.NF(number of field):代表一行中的字段数
awk的内置函数
字符串函数:
1.length()
[root@localhost check]# cat /etc/passwd |awk -F: 'length($3)==3 {print $1,$3}'
[root@localhost check]# cat /etc/passwd |awk -F: 'length($1)>=5 && length($1)<=10 && $7 ~/bash/ && $3>500 {print $1,$3,$7}'
2.其他函数:
next():跳过当前行。
[root@localhost check]# seq 10 |awk '{if (NR%2==1) next;else print $1,$2}'
关于awk的高级部分等有时间了再整理。