linux学习笔记--awk命令详解
作用:数据处理工具,用于把一行中分成数个字段处理(切割)
- 语法规则:
awk '条件类型 1 {操作1} 条件类型2 {操作2} ...' filename
awk主要处理一行内的数据,默认的分隔符为“空格键”或“TAB键”
- 例:找出登录这着的账号与ip
[root@localhost ~]# last -n 5
root pts/1 192.168.43.99 Thu Mar 12 10:25 still logged in
root tty1 Thu Mar 12 10:24 still logged in
root pts/0 192.168.43.99 Thu Mar 12 09:55 - 10:26 (00:31)
reboot system boot 3.10.0-1062.12.1 Thu Mar 12 09:55 - 11:12 (01:17)
root pts/0 192.168.43.99 Wed Mar 11 17:06 - down (00:09)
wtmp begins Sat Nov 16 04:06:53 2019
[root@localhost ~]# last -n 5 | awk '{print $1 " " $3}'
root 192.168.43.99
root Thu
root 192.168.43.99
reboot boot
root 192.168.43.99
wtmp Sat
几个变量的说明($0 $1 $2 ...)
上面例子中$1是root,是该行第一栏的内容,$3是192.168.43.99 ,是该行第三栏的内容。$0代表一整行数据。
awk处理流程
- 读入第一行,将第一行数据写入$0 $1 $2...中
- 根据“条件类型”的限制判断是否进行后面“操作”(上例中因为每行都要操作,因此没有设置条件类型)
- 若为多行,则在重复执行1,2
awk内置变量
变量名称 | 含义 |
---|---|
NF | 每行($0)拥有的字段数 |
NR | 目前awk所处理第几行 |
FS | 目前分割字符,默认为空格键 |
FILENAME | awk浏览的文件名 |
... | ... |
- 例:在上例中列出每行行号($1);列出目前处理行数;列出该行字段数
[root@localhost ~]# last -n 5 | awk '{print $1 " lines: " NR " columns:" NF}'
root lines: 1 columns:10
root lines: 2 columns:9
root lines: 3 columns:10
reboot lines: 4 columns:11
root lines: 5 columns:10
lines: 6 columns:0
wtmp lines: 7 columns:7
awk逻辑运算符
运算单元 | 含义 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
实验练习
- 例:列出/etc/passwd中第一个字段用户,第三个字段UID,并设置仅查看第三栏小于10的数据
[root@localhost ~]# cat /etc/passwd | awk '{FS=":"} $3<10 {print $1 " " $3}'
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
这有一个为问题:第一行没有正确分割,因为读第一行时默认还是以空格键分割 (--感觉是个缺陷呀)
解决方法:预先设置awk变量,利用BEGIN关键词
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3<10 {print $1 " " $3}'
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
- 例
[root@localhost ~]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# awk -F: '/root/ {print $7}' /etc/passwd //-F: 等效于FS=":"
/bin/bash
/sbin/nologin
- 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容
[root@localhost ~]# awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd | head -n 5
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
filename:/etc/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin
filename:/etc/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
- 使用printf替代print,可以让代码更加简洁,易读
[root@localhost ~]# awk -F: '{printf ("filename:%10s, linenumber:%3s,column:%3s,content:%4s
",FILENAME,NR,NF,$0)}' /etc/passwd | head -n 5
filename:/etc/passwd, linenumber: 1,column: 7,content:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd, linenumber: 2,column: 7,content:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd, linenumber: 3,column: 7,content:daemon:x:2:2:daemon:/sbin:/sbin/nologin
filename:/etc/passwd, linenumber: 4,column: 7,content:adm:x:3:4:adm:/var/adm:/sbin/nologin
filename:/etc/passwd, linenumber: 5,column: 7,content:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
- 打印/etc/passwd/的第二行信息
[root@localhost ~]# awk -F: 'NR==2{print "filename: "FILENAME, $0}' /etc/passwd
filename: /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin
- 指定特定的分隔符,查询第一列
[root@localhost ~]# awk -F ":" '{print $1}' /etc/passwd | head -n 8
root
bin
daemon
adm
lp
sync
shutdown
halt
- 指定特定的分隔符,查询最后一列
[root@localhost ~]# awk -F ":" '{print $NF}' /etc/passwd | tail -n 5
/bin/bash
/bin/bash
/bin/bash
/bin/bash
/sbin/nologin
- 指定特定的分隔符,查询倒数第二列
[root@localhost ~]# awk -F ":" '{print $(NF-1)}' /etc/passwd | head -n 5
/root
/bin
/sbin
/var/adm
/var/spool/lpd
- 获取第12到31行的第一列的信息
[root@localhost ~]# awk -F ":" '{if(NR<31 && NR >12) print $1}' /etc/passwd
nobody
systemd-network
dbus
polkitd
libstoragemgmt
colord
rpc
saslauth
abrt
setroubleshoot
rtkit
radvd
gluster
chrony
qemu
unbound
tss
usbmuxd
- 多分隔符的使用 (这里以/为分隔符,多个分隔符利用[]然后在里面写分隔符即可 )
[root@localhost ~]# awk -F "[/]" 'NR == 4 {print $0,"
",$1}' /etc/passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
adm:x:3:4:adm: