【Linux系列教程】awk工具
一、关于awk工具
- 工作流程
- 默认情况下,awk可以使用空白字符分割文本, awk内部可以分别$1, $2变量代表第一段内容
- -F选项指定分割符
- 逐行处理
- 作用
- 显示文本
二、awk基本命令格式
# awk [option] 'script' 文件名称 文件名称
# awk [option] 'PATTERN{action}' 文件名称 文件名称
常用
action
- printf
1.print操作
[root@master ~]# sed -n '1p' /etc/passwd #显示第一行
root:x:0:0:root:/root:/bin/bash
[root@master ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1}' #使用管道符处理上一个命令的结果,以":"为分隔符,显示第一个字段
root
[root@master ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1,$7}' #以":"为分隔符,显示第一个字段和第七个字段
root /bin/bash
[root@master ~]# sed -n '1p' /etc/passwd | awk -F: '{print $0}' #特殊$0查看一整字段
root:x:0:0:root:/root:/bin/bash
支持
自定义
输出
awk '{print "自定义字段"$显示的字段数}'
[root@master ~]# sed -n '1p' /etc/passwd | awk -F: '{print "用户名:"$1,"终端:"$7}'
用户名:root 终端:/bin/bash
2.printf操作
- 格式化输出内容
- 使用格式
- printf “格式格式”,内容,内容
- 占位符
- %s 字符串
- %d 整数
- %f 浮点数
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{print $1,$6}' #没有用printf格式化处理之前
root /root
bin /bin
daemon /sbin
adm /var/adm
lp /var/spool/lpd
sync /sbin
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{printf "%-10s%s\n", $1,$6}'
root /root
bin /bin
daemon /sbin
adm /var/adm
lp /var/spool/lpd
sync /sbin
%s
代表字符串,中间数字10
,设置字符宽度为10
,-
修改默认右对齐为左对齐,\n
为换行符
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{printf "%10s%s\n", $1,$6}' #如果不添加“-”就会默认右对齐
root/root
bin/bin
daemon/sbin
adm/var/adm
lp/var/spool/lpd
sync/sbin
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{printf "%-10s%s", $1,$6}'
root /rootbin /bindaemon /sbinadm /var/admlp /var/spool/lpdsync /sbin[root@master ~]#
#可以看到没有\n换行输出的结果,和命令提示符连在一起了,格式很乱
因为我们
新增
了自定义
字符,所以前面%s
要多加2个
用来控制那2个字符的格式
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{printf "%s%-10s%s%s\n", "用户名:",$1, "默认终端:",$7}'
用户名:root 默认终端:/bin/bash
用户名:bin 默认终端:/sbin/nologin
用户名:daemon 默认终端:/sbin/nologin
用户名:adm 默认终端:/sbin/nologin
用户名:lp 默认终端:/sbin/nologin
用户名:sync 默认终端:/bin/sync
同样可以控制我们
自定义
字符的宽度
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{printf "%-5s%-10s%-6s%s\n", "用户名:",$1, "默认终端:",$7}'
用户名: root 默认终端: /bin/bash
用户名: bin 默认终端: /sbin/nologin
用户名: daemon 默认终端: /sbin/nologin
用户名: adm 默认终端: /sbin/nologin
用户名: lp 默认终端: /sbin/nologin
用户名: sync 默认终端: /bin/sync
3.awk常用内置变量
FS
相当于
-F
选项的作用
保存行分割符
,默认空白
[root@master ~]# sed -n 'p' /tmp/passwd | awk -v FS=":" '{print $1,$7}'
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
和
-F
参数作用一样,都是已:
为分隔符
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: '{print $1,$7}'
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
OFS
指定awk显示
多段
内容时,多段内容间的分隔符
(自定义分隔符)
默认空白
字符
[root@master ~]# sed -n 'p' /tmp/passwd | awk -F: -v OFS="---->" '{print $1,$7}'
root---->/bin/bash
bin---->/sbin/nologin
daemon---->/sbin/nologin
adm---->/sbin/nologin
lp---->/sbin/nologin
sync---->/bin/sync
NR
记录行号
处理多个
文件时,所有文件的行号是连续
记录的
[root@master ~]# awk '{print NR}' /etc/hosts /etc/fstab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master ~]# awk 'NR==3{print $0}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin #指定显示的行
FNR
记录行号
处理多个
文件时,所有文件的行号是独立
记录的
[root@master ~]# awk '{print FNR}' /etc/hosts /etc/fstab
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
NF
记录
awk
分割行后
的段数
[root@master ~]# awk -F: '{print $NF}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
[root@master ~]# cat /tmp/file01
centos redhat
debian ubuntu Kubuntu Xubuntu
WindowsXP Windows7 Windows8 Windows8.1 Windows10 Windows11
MacOS
[root@master ~]# awk '{print $NF}' /tmp/file01
redhat
Xubuntu
Windows11
MacOS
FILENAME
保存awk正在处理的文件名
[root@localhost ~]# awk '{print FILENAME}' /tmp/file01
/tmp/file01
/tmp/file01
/tmp/file01
/tmp/file01
uniq
去重
[root@master ~]# awk '{print FILENAME}' /tmp/file01 | uniq
/tmp/file01
4.awk自定义变量
awk -v 自定义变量名="值"
[root@master ~]# awk -v name="wsjj" '{print "hello", name}' /etc/fstab
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
hello wsjj
三、awk常用文本处理模式
1.表达式
- 比较运算符
- ==, >, >=, <, <=, !=
- 数据 ~ 正则表达式
- 判断数据是否可以被正则表达式
- 数据 !~ 正则表达式
- 逻辑运算符
- && 并且
- || 或者
[root@master ~]# awk '{print $0}' /tmp/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
[root@master ~]# awk -F: '$3>=1 && $3<=999{print $1}' /tmp/passwd
bin
daemon
adm
lp
sync
2./正则表达式/
[root@master ~]# awk '/^\/dev/{print $0}' /etc/fstab #“\”为转译符
/dev/mapper/centos-root / xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
[root@master ~]# awk '/^root/{print $0}' /tmp/passwd
root:x:0:0:root:/root:/bin/bash
3./正则表达式/,/正则表达式/
[root@localhost ~]# awk '/Sep 26 09:02:30/,/Sep 26 09:18:04/{print $0}' /var/log/messages
/正则表达式匹配的字符或数字/
4.BEGIN{}
定义
awk
开始处理内容前
执行的操作
[root@master ~]# awk -F: 'BEGIN{print "----以下是用户和默认终端----"}{print $1,$7}' /tmp/passwd
----以下是用户和默认终端----
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
5.END{}
定义
awk
处理内容后
要执行的操作
[root@master ~]# awk -F: 'BEGIN{print "----以下是用户和默认终端----"}{print $1,$7}END{print "----结束----"}' /tmp/passwd
----以下是用户和默认终端----
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
----结束----
[root@master ~]# awk -v number=0 '{number++}END{print number}' /tmp/passwd
6 #可以看到文件有6行数据
四、awk条件判断
1.语法格式
if (条件) {操作}
if (条件) {操作} else {操作}
if (条件) {操作} else if (条件)
判断管理员与普通账户
[root@master ~]# awk -F: '{if($3==0) {print $1 "是管理员用户"} else {print $1 "是普通用 户"}' /tmp/passwd
root是管理员用户
bin是普通用户
daemon是普通用户
adm是普通用户
lp是普通用户
sync是普通用户
统计bash用户和nologin用户的数量
[root@master ~]# awk -F: -v bash_number=0 -v nologin_numer=0 '{if($7=="/bin/bash") {bash_number++} else if($7=="/sbin/nologin") {nologin_number++}}END{print "bash用户数",bash_number, "nologin用户数",nologin_number}' /etc/passwd
bash用户数 4 nologin用户数 18
五、循环
1.for循环
for(变量定义; 循环条件; 改变变量的值) {操作}
for(i=1; i<=10; i++)
[root@master ~]# awk -F: '{for(i=1;i<=7;i++){if(length($i)>=5) {print $i}}}' /tmp/passwd/root
/bin/bash
/sbin/nologin
daemon
daemon
/sbin
/sbin/nologin
/var/adm
/sbin/nologin
/var/spool/lpd
/sbin/nologin
/sbin
/bin/sync
六、数组
1.定义数组
[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]}}'
martin
robin
lz
3.数组支持任意数据作为下标
[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 test[i]}}'
河北
天津
北京
统计httpd的UV和PV
UV 用户访问量
PV 页面访问量
# 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")}'