#作者:张桐瑞
一、awk工具介绍
工作流程
- 默认情况下,awk可以使用空白字符分割文本, awk内部可以分别$1, $2变量代表第一段内容 $0 :没有被分割的整行内容
- -F选项指定分割符
- 逐行处理
作用
- 显示文本
二、awk基本使用
# awk [option] 'script' 文件名称 文件名称
# awk [option] 'PATTERN{action}' 文件名称 文件名称
常用action:
print
printf 格式化输出(例:左对齐,右对齐)
1、print操作
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1}'
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $0}'
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1, $3}'
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{print "用户名:",$1}'
[root@localhost ~]# rpm -qa | grep php | awk -F-5 '{print "rpm -e --nodeps", $1}' | bash
卸载软件 rpm -e --nodeps
2、printf操作
格式化输出内容
- 使用格式
- printf “格式格式”,内容,内容
- 占位符
%s 字符串
%d 整数
%f 浮点数
- 占位符
- printf “格式格式”,内容,内容
[root@localhost ~]# awk '{printf "%s", $2}' /tmp/file01
[root@localhost ~]# awk '{printf "%s%s", $2, $3}' /tmp/file01
手动在引号里 加\n 换行
- 设置字符的宽度
- %10s
[root@localhost ~]# awk '{printf "%20s", $2}' /tmp/file01
默认数据在指定的宽度字符是以右对齐的方式显示
- 设置左对齐
- %-10s
[root@localhost ~]# awk '{printf "%-20s", $2}' /tmp/file01
- 默认没有换行,如果需要换行,手动添加换行符\n
[root@localhost ~]# awk '{printf "%-20s\n", $2}' /tmp/file01
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{printf "%-8s%-16s\n", $1, $7}'
[root@localhost ~]# df -hT | sed -n '/^\/dev/p' | awk '{printf "%-10s%-30s%-10s%-12s%-10s%-8s\n","磁盘名称:", $1, "挂载目录:", $7, "剩余空间:", $6}'
三、awk常用内置变量
1、FS
- 相当于-F选项的作用
- 保存行分割符,默认空白
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -v FS=":" '{print $1}'
2、OFS
- 指定awk显示多段内容时,多段内容间的分隔符
- 默认空白字符
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -v OFS="--->" -F: '{print $1, $7}'
root--->/bin/bash
3、NR
- 记录行号
- 处理多个文件时,所有文件的行号是连续记录的
[root@localhost ~]# awk '{print NR}' /etc/hosts /etc/redhat-release
[root@localhost ~]# awk 'NR==3{print $0}' /etc/passwd
NR<=3 输出三行内容
4、FNR
- 记录行号
- 处理多个文件时,所有文件的行号是独立记录的
[root@localhost ~]# awk '{print FNR}' /etc/hosts /etc/redhat-release
5、NF
- 记录awk分割行后的段数
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print NF}'
[root@localhost ~]# awk '{print $NF}' /tmp/file01 //每一行分割的段数不同
{print NF} : 被分割的段数
$NF :就是被分割的最后一段
6、FILENAME
- 保存awk正在处理的文件名
[root@localhost ~]# awk '{print FILENAME}' /tmp/file01
/tmp/file01
/tmp/file01
/tmp/file01
[root@localhost ~]# awk '{print FILENAME}' /tmp/file01 | uniq
/tmp/file01
四、awk自定义变量
-v 变量名称=值
[root@localhost ~]# awk -v name="martin" '{print "hello", name}' /etc/fstab
[root@localhost ~]# awk -v number=100 '{print number}' /etc/fstab
五、awk常用文本处理模式
1、表达式
- 比较运算符
- ==, >, >=, <, <=, !=
- 数据 ~ 正则表达式
- 判断数据是否可以被正则表达式
- 数据 !~ 正则表达式
- 逻辑运算符
- && 并且
- || 或者
[root@localhost ~]# awk -F: '$3>=1 && $3 <= 999{print $1}' /etc/passwd
[root@localhost ~]# awk -F: '$7=="/sbin/nologin"{print $1}' /etc/passwd
[root@localhost ~]# awk -F: '$7 ~ "nologin$"{print $1}' /etc/passwd
[root@localhost ~]# df -hT | grep "^/dev" | awk '+$6>20{print "磁盘名称:", $1, "剩余空间", $5, "挂载目录:", $NF}'
+$6>20
转换成数字
2、/正则表达式/
[root@localhost ~]# netstat -antp | awk '/^tcp/{print $0}'
[root@localhost ~]# awk -F: '/^[rhg]/{print $1}' /etc/passwd
[root@localhost ~]# ls -l /etc/ | awk '/^-/{print $NF}'
3、/正则表达式/,/正则表达式/
[root@localhost ~]# awk '/Sep 26 09:02:30/,/Sep 26 09:18:04/{print $0}' /var/log/messages
4、BEGIN{}
- 定义awk开始处理内容前执行的操作
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: 'BEGIN{print "----数据开始----"}{print $1,$7}'
[root@localhost ~]# awk 'BEGIN{name="martin"; print name}'
5、END{}
- 定义awk处理内容后要执行的操作
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: 'BEGIN{print "----数据开始-----"}{print $1, $7}END{print "----数据结束----"}'
[root@localhost ~]# awk -v number=0 '{number++}END{print number}' /etc/passwd
六、awk条件判断
1、语法
- if (条件) {操作}
- if (条件) {操作} else {操作}
- if (条件) {操作} else if (条件) {操作}
[root@localhost ~]# awk -F: '{if($3==0) {print $1, "是管理员"} else {print $1, "是普通用户"}}' /etc/passwd
[root@localhost ~]# awk -F: -v bash_number=0 -v nologin_number=0 '{if($7=="/bin/bash") {bash_number++} else if($7=="/sbin/nologin") {nologin_number++}}END{print "bash用户数", bash_number, "nologin用户数", nologin_number}' /etc/passwd
七、awk循环
awk 本身就是按行循环,再来一个子循环就是循环每一行的每一段
1、for循环语法
for(变量定义; 循环条件; 改变变量的值) {操作}
for(i=1; i<=10; i++)
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{for(i=1; i<=7; i++) {if(length($i)>=5) {print $i}}}'
[root@localhost ~]# awk '{for(i=1; i<=NF; i++) {if(length($i)>=4) {print $i}}}' /tmp/file01
八、awk数组
1、定义数组
[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"}'
[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"; print test[2]}'
robin
2、获取数组中所有数据
[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"; for(i=1; i<=3; i++) {print test[i]}}'
3、数组支持以任意数据作为下标
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"}'
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; print test["robin"]}'
河北
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print i}}'
robin
lz
martin
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print test[i]}}'
河北
天津
北京
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print "姓名:", i, "住址:", test[i]}}'
遍历数组data
[root@localhost ~]# awk -F: '{data[$7]++}END{for(i in data) {print i, data[i]}}' /etc/passwd
[root@localhost ~]# netstat -antp | awk '/^tcp/{tcp_number[$6]++}END{for(i in tcp_number) {print i, tcp_number[i]}}'
# awk '{uv[$1]++}END{for(i in uv) {print i, uv[i]}}' access_log
# awk '{pv[$7]++}END{for(i in pv) {print i, pv[i]}}' access_log
九、awk的内置函数
1、split(字符串,数组,行分割符)
使用分割符分割字符串, 将分割后的字符串保存到指定数组
# awk 'BEGIN{split("a-b-c", data, "-"); print data[1]}'
# awk 'BEGIN{split("a-b-c", data, "-"); print data[2]}'
# awk 'BEGIN{split("a-b-c", data, "-"); print data[3]}
2、length(string)
返回string字符串的字符个数
# awk 'BEGIN{print length("shell")}'
3、substr(string,start [,length])
取string字符串中的子串,从start开始,取length个;start从1开始计数
# awk 'BEGIN{data=substr("hello",2, 3); print data}'
4、system(command)
支持在awk内部调用shell命令
# awk 'BEGIN{system("ifconfig enp2s0")}'
5、systime()
返回系统当前时间
# awk 'BEGIN{print systime()}'
# awk 'BEGIN{now=systime(); print strftime("%F_%T", now)}'
6、tolower(string)
将string中的所有字母转为小写
# awk 'BEGIN{print tolower("aBcD")}'
7、toupper(string)
将string中所有字母转换为大写
# awk 'BEGIN{print toupper("aBcD")}'