awk将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作数据可以来自标准输入也可以是管道或文件。
20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次
默认情况下字段的分隔符为空格或tab键,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个""字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。
在使用awk命令的过程中,可以使用逻辑操作符"&&“表示"与”、“||“表示"或”、”!“表示"非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。
awk 后面接两个单引号并加上大括号{ }来设置想要对数据进行的处理操作,awk 可以处理后续接的文件,也可以读取来自前个命令的标准输出。
awk [options] 'program' var=value file…
awk [选项] '模式条件' 文件1 文件2...
注意事项
选项 | 说明 |
---|---|
-v | 定义变量 |
-F | 指定分隔符 |
内置变量 | 说明 |
---|---|
NR | 当前处理的行的行号(序数) |
NF | 当前处理的行的字段个数 |
FS | 列分隔符,指定每行文本的字段分隔符,默认为空格或制表位。 与 “ -F ” 作用相同 |
OFS | 输出内容的列分隔符 |
RS | 行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n" |
$0 | 当前处理的行的整行内容 |
$n | 当前处理行的第n个字段(第n列) |
FILENAME | 被处理的文件名 |
#打印所有内容
[root@localhost data]#awk '{print}' /etc/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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
#打印行的内容及行号
[root@localhost data]#awk '{print NR,$0}' /etc/passwd
#NR表示打印行号;$0表示打印所有内容
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin
12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13 nobody:x:99:99:Nobody:/:/sbin/nologin
14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
15 dbus:x:81:81:System message bus:/:/sbin/nologin
16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
17 abrt:x:173:173::/etc/abrt:/sbin/nologin
18 libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
19 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
20 colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
21 saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
22 rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
#打印第2行内容
[root@localhost data]#awk 'NR==2{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
#打印第2行至第6行的内容
[root@localhost data]#awk 'NR==2,NR==6{print}' /etc/passwd
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
#打印第2行至第6行的内容
[root@localhost ~]#awk 'NR>=2&&NR<=6{print}' /etc/passwd
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开头的行
[root@localhost data]#awk '/^root/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#匹配文件中以bash结尾的行
[root@localhost data]#awk '/bash$/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash
#打印偶数行
[root@localhost ~]#awk 'NR%2==0{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
chrony:x:995:991::/var/lib/chrony:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
geoclue:x:994:989:User for geoclue:/var/lib/geoclue:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
sssd:x:992:987:User for sssd:/:/sbin/nologin
gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
#打印奇数行
[root@localhost ~]#awk 'NR%2==1{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
setroubleshoot:x:993:988::/var/lib/setroubleshoot:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash
zhangsan:x:1001:1001::/home/zhangsan:/bin/bash
getline工作过程:
1)当getline左右无重定向符号(“<”)或者管道符号(“|”)时,awk首先读取的是第一行,而getline获取的是光标跳转至下一行的内容(也就是第二行)
原因:getline运行之后awk会改变NF,NR,$0,FNR等内部变量,所以此时读取$0的行号不再为1,而是2。
注意:
FNR:awk当前读取的记录数,其变量值小于等于NR,(比如说当读取完第一个文件后,读取第二个文件,FNR是会从0开始进行,而NR不会)。因此读取两个或两个以上的文件,NR==FNR,可以判断是不是在读取第一个文件。
2)当getline左右有管道符号或重定向符时,getline则作用定向输入文件,由于文件是刚打开,并没有被awk读入一行,而只是getline读入,所以getline返回的是文件的第一行,而不是跳转至一行输入
#打印偶数行
[root@localhost ~]#seq 10 |awk '{getline;print $0}'
2
4
6
8
10
##先进行getline跳转至下一行,awk读取跳转后的整行内容,经过逐步跳转读取,形成了只显示偶数行
#打印奇数行
[root@localhost etc]#seq 10 |awk '{print $0;getline}'
[root@localhost ~]#seq 10 |awk '{print $0;getline}'
1
3
5
7
9
##先进行awk打印第一行的内容,结束后按照正常顺序打印,但是getline进行跳转,第二行不打印了,最终呈现出奇数行打印
格式:awk ‘BEGIN{…};{…};END{…}’ 文件
处理过程:
在 awk 处理指定的文本之前,需要先执行 BEGIN{…} 模式里的命令操作
中间的 {…} 是真正用于处理文件的命令操作
在 awk 处理完文件后才会执行 END{…}模式里的命令操作。END{ } 语句块中,往往会放入打印结果等语句。
#以冒号为分隔符,取第一列
[root@localhost data]#awk -F ':' '{print $1}' /etc/passwd |head
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
#提取uid号大于等于1000的用户
[root@localhost data]#awk -F: '$3>=1000{print $3,$1}' /etc/passwd
65534 nfsnobody
1000 liuyanfen
1001 zhangsan
##先用-F指定分隔符为":" ,文件以":"分割的第三列为uid,uid大于1000的打印第三列和第一列,也就是uid和用户
#提取uid号大于1000的用户
[root@localhost data]#awk -F: '!($3<=1000){print $3,$1}' /etc/passwd
65534 nfsnobody
1001 zhangsan
#用if语句提取uid号大于等于1000的用户
[root@localhost data]#awk -F: '{if($3>=1000){print $3,$1}}' /etc/passwd
65534 nfsnobody
1000 liuyanfen
1001 zhangsan
#提取磁盘已经使用量
[root@localhost data]#df|awk '{print $5}'|tail -n +2|tr -d %
10
0
0
1
0
4
1
1
100
#方法二:提取磁盘已经使用量
[root@localhost data]#df |awk -F"[ %]+" '{print $5}'|tail -n +2
##[ %] 一个字符,看到空格和%,都当作分隔符。 + 表示一个以上
#方法三:提取磁盘已经使用量
[root@localhost data]#df |awk -F"[[:space:]]+|%" '{print $5}'|tail -n +2
[root@localhost data]#ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.10.11 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::53e9:a034:7de9:f2b9 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:42:0c:18 txqueuelen 1000 (Ethernet)
RX packets 127333 bytes 173110407 (165.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 32293 bytes 2132652 (2.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#提取ip地址
[root@localhost data]#ifconfig ens33|awk 'NR==2{print $2}'
192.168.10.11
java中
(条件表达式)?(A表达式或者值):(B表达式或者值)
解释:
条件表达式成立(为真)时,会取冒号前面的值A。 - 条件表达式不成立(为假)时,会取冒号后面的值B。
shell中
[ 条件表达式 ] && A || B
解释:
条件表达式成立(为真)时,会取||前面的值A。 - 条件表达式不成立(为假)时,会取||后面的值B。
格式:awk ‘(条件表达式)?(A表达式或者值):(B表达式或者值)’
[root@localhost data]#awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd |sed -n '1,6p'
0 root:x:0:0:root:/root:/bin/bash
1 bin:x:1:1:bin:/bin:/sbin/nologin
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
7 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
5 sync:x:5:0:sync:/sbin:/bin/sync
#比较passwd文件中第三列和第四列的大小,取他们结果较大的值,赋于变量max 并且输出max及其所在行的全部内容
筛选方法 | 说明 |
---|---|
$n (><==) | 用于对比数值 |
$n~“字符串” | 代表第n个字段,包含某个字符串的作用 |
$n!~“字符串” | 代表第n个字段,不好含某个字符串的作用 |
$n==“字符串” | 代表第n个字段为某个字符串的作用 |
$n!=“字符串” | 代表第n个字段不为某个字符串的作用 |
$NF | 代表最后一个字段 |
[root@localhost data]#awk -F: '$7~"bash"{print $1,$NF}' /etc/passwd
root /bin/bash
liuyanfen /bin/bash
zhangsan /bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第7列字段中包含bash字符的行,打印每行的第1列和最后1列
[root@localhost data]#awk -F: '$7!~"nologin"{print $1,$NF}' /etc/passwd
root /bin/bash
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
liuyanfen /bin/bash
zhangsan /bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第7列字段中不包含nologin字符的行,打印每行的第1列和最后1列
[root@localhost data]#awk -F: '($6=="/home/liuyanfen")&&($7=="/bin/bash"){print $0}' /etc/passwd
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第6字段为/home/liuyanfen,第7字段为/bin/bash的行
内置变量 | 说明 |
---|---|
NR | 当前处理的行的行号(序数) |
NF | 当前处理的行的字段个数 |
FS | 列分隔符,指定每行文本的字段分隔符,默认为空格或制表位。 与 “ -F ” 作用相同 |
OFS | 输出内容的列分隔符 |
RS | 行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n" |
$0 | 当前处理的行的整行内容 |
$n | 当前处理行的第n个字段(第n列) |
FILENAME | 被处理的文件名 |
$NF | 最后一段 |
$(NF-1) | 倒数第二段 |
[root@localhost data]#awk -F: '{print NR}' /etc/passwd
1
2
3
4
5
6
#显示行号
[root@localhost data]#awk -F: '{print $1"\t"NR}' /etc/passwd
root 1
bin 2
daemon 3
adm 4
lp 5
sync 6
#制表符
[root@localhost data]#awk -F: '{print NR"\t"$1}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
#NR在前面时,行号数字显示在前
[root@localhost data]#awk -F: 'NR==2{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
#显示/etc/passwd文件的第2行
[root@localhost ~]#awk 'NR%2==0{print}' /etc/passwd
#打印偶数行
[root@localhost ~]#awk 'NR%2==1{print}' /etc/passwd
#打印奇数行
[root@localhost data]#awk -F: 'NR==2,NR==6 {print}' /etc/passwd
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
#显示第2行至第6行的内容
#显示前10行中每行有几个字段
[root@localhost data]#awk -F: '{print NF}' /etc/passwd |head
7
7
7
7
7
7
7
7
7
7
#显示前10行中每一行的最后一列
[root@localhost data]#awk -F: '{print $NF}' /etc/passwd |head
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
/sbin/nologin
/sbin/nologin
#显示前10行中每一行的倒数第2列
[root@localhost data]#awk -F: '{print $(NF-1)}' /etc/passwd |head
/root
/bin
/sbin
/var/adm
/var/spool/lpd
/sbin
/sbin
/sbin
/var/spool/mail
/root
[root@localhost data]#awk -v FS=: '{print $1FS$3}' /etc/passwd|head
root:0
bin:1
daemon:2
adm:3
lp:4
sync:5
shutdown:6
halt:7
mail:8
operator:11
[root@localhost data]#echo A B C D |awk '{OFS="|";print $0;$1=$1;print $0}'
A B C D
A|B|C|D
#$1=$1是激活$0的重新赋值
awk 从文件中读取资料时,将根据 RS 的定义把资料切割成许多条记录, 而 awk 一次仅读入一条记录进行处理。内置变量 RS 的预设值是"\n"。
但是也可以在使用 BEGIN 模式在操作前进行行分隔符的改变。
[root@localhost data]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost data]#
[root@localhost data]#echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
#通过BEGIN模式在awk命令执行前将分隔符改为":",然后打印行号及每一行内容
[root@localhost data]#awk -F: 'NR==2{print FILENAME}' /etc/passwd
/etc/passwd
#显示当前处理文件的名字
[root@localhost data]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}'
10
[root@localhost data]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[1]}'
20
[root@localhost ~]#q=(10 10 10 20 30 20 30 20 40 10 30 10)
[root@localhost ~]#echo ${q[@]}|awk -v RS=' ' '!a[$1]++'
10
20
30
40
关系表达式结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
[root@localhost data]#seq 10 |awk 0
[root@localhost data]#
[root@localhost data]#seq 10 |awk 1
1
2
3
4
5
6
7
8
9
10
[root@localhost data]#seq 10 |awk 2
1
2
3
4
5
6
7
8
9
10