awk是文本三剑客之一,其实awk是一种语言,该语言的创始者定义为”生成报表和格式化文本输出“awk有不少种版本,这里介绍的是GUN awk(gawk)linux
第一步:执行BEGIN{action}语句块中的语句,该语句块不依赖于文件,awk在执行是,将在读取文件以前执行该语句中的语句块,经常使用语变量的初始化,打印输出表格的表头。
第二步:从文件、标准输入、上一条命令输出结果输入地区一行,而后进行pattern{aciton}语句块,它将逐行扫描文件,从第一行到最后一行。若没有提供pattern语句,则默认执行打印{print},即打印每个读取到的行。
第三步:当读至文件最后时,执行END{action}语句块。一般用于汇总在pattern语句中执行的过程正则表达式
选项
-F"指定分隔符"
-v 自定义变量:定义变量
awk {print} file
awk将把file文件中的每一行都读取一遍,而后输出在终端上
输入内置变量在文本中表明以下图所示apache
[root@centos6 ~]#awk -F: -v OFS="===" -v ORS="####" '{print $1,$2}' /etc/passwd #将输出间隔符换为===将换行符换为###输出结果以下 root===x####bin===x####daemon===x####adm===x####lp===x####sync===x####shutdown===x####halt===x####mail===x####uucp===x####operator===x####games===x####gopher===x####ftp===x####nobody===x####vcsa===x####saslauth===x####postfix===x####sshd===x####lin===x####tcpdump===x####hacker===x####dbus===x####test===x####apache===x####[root@centos6 ~]#
实例一centos
[root@centos6 ~]#awk -F: '{print $1,$3}' /etc/passwd #表示已“ : ”为分隔符,取第一列和第三列,而后将结果输出出来 root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10 operator 11
awk命令的print打印内容也能够不与文件有关,若没有关系,则表示文件有多少行内容,就会打印本身所指定的内容,而在awk中,处理动做中的字母若不用" "引上则表示使用变量,因此若须要输出字符串则须要用“ ”引上。数字则不须要。
实例1、输入分隔符数组
[root@centos6 ~]#echo {1..10} 1 2 3 4 5 6 7 8 9 10 [root@centos6 ~]#echo {1..10}|awk -v FS=" " '{print $1,$3}' 1 3
这里表示本来输出结果为1到时,拿FS内置变量举例,设置空白字符为分隔符(默认分隔符就是空白字符,因此不指定结果也是同样的,这里只是为了举例说明),取1,3列,
实例2、替换输出分隔符bash
[root@centos6 ~]#echo {1..10} | awk -v OFS=":" '{print $1,$2,$3}' 1:2:3
这里OFS内置变量表示将输出结果分隔符变成:,取1,2,3列
实例3、分别显示两个文本的行号app
[root@centos6 ~]#awk '{print FNR,$0}' /etc/fstab /etc/issue #表示分别显示每个文件的行号 1 2 # 3 # /etc/fstab 4 # Created by anaconda on Fri Mar 9 08:50:54 2018 5 # 6 # Accessible filesystems, by reference, are maintained under '/dev/disk' 7 # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info 8 # 9 /dev/mapper/vgentos6-LogVol03 / ext4 defaults 1 1 10 /dev/mapper/vgentos6-LogVol02 /app ext4 defaults 1 2 11 UUID=8f86cc7e-f593-467d-b823-eae6610616a1 /boot ext4 defaults 1 2 12 /dev/mapper/vgentos6-LogVol00 /var ext4 defaults 1 2 13 /dev/mapper/vgentos6-LogVol01 swap swap defaults 0 0 14 tmpfs /dev/shm tmpfs defaults 0 0 15 devpts /dev/pts devpts gid=5,mode=620 0 0 16 sysfs /sys sysfs defaults 0 0 17 proc /proc proc defaults 0 0 18 /dev/cdrom /mnt/base auto defaults 0 0 1 CentOS release 6.9 (Final) 2 Kernel \r on an \m 3
在输出内容时,print输出只能输出规定格式的内容,不能自定义格式,因此想要让输出结果根据本身所须要的格式输出就须要用printf来定制格式
printf使用格式
awk ‘{printf "格式1 格式 ",$1,$2}’,格式必须和须要输出的列一一对应
实例1、格式化输出,让文本左对齐ssh
[root@centos6 ~]#awk -F: '{printf "%-20s %-20d\n",$1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10
由于printf不会自动换行,因此在规定好的格式后面增长\n来起到换行符的做用,其中-表明左对齐,若须要右对齐则直接填整数便可tcp
awk也能够进行数字间的运算,不但支持整数,并且支持小数
实例1、两个数之间的运算ide
[root@centos6 ~]#awk 'BEGIN{print 5+10}' 15 [root@centos6 ~]#awk 'BEGIN{print 5.5+10.5}' 16 [root@centos6 ~]#awk 'BEGIN{print 40/3}' 13.3333
在赋值操做符中,sum+=i,就至关于sum=sum+i,
实例1、将100之内的数相加
seq 100 | awk '{sum+=$1}END{print sum}'
5050
由于awk原本就是针对行行的循环,能够根据这个特性将1到100相加在END部分将sum值输出,就实现了100百之内数相加
实例2、变量的自增
[root@centos6 ~]#awk '{print i++}' /etc/passwd 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
在awk中,变量一旦与运算符号结合使用,将认为该变量的初始值为0,这个这条语句表示从零开始/etc/passwd文件有多少行,i变量将自增几回
awk模式通配符~,表示左边的内容是否和右边内容匹配包含,!~则表示不匹配
实例1、在文件中查找包含某字符的行
[root@centos6 ~]#awk -F: '$0 ~ /root/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
查看passwd这个文件包含root的行,并将其打印到终端
实例2、查找passwd文件中全部/bin/bash的行
[root@centos6 ~]#awk -F: '$0 ~ "/bin/bash"' /etc/passwd root:x:0:0:root:/root:/bin/bash lin:x:500:500::/home/lin:/bin/bash hacker:x:501:501::/home/hacker:/bin/bash test:x:502:502::/home/test:/bin/bash
因所搜内容中也包含 ” / “ 因此须要将搜索内容用双引号引发来
&&:表示同时知足两个条件
||:表示知足两个条件中的一个便可
!:表示取匹配结果的反值
实例1、取同时知足两个条件的结果&&
[root@centos6 ~]#awk -F: '$3>=50 && $3<=100{print $1,$3}' /etc/passwd nobody 99 vcsa 69 postfix 89 sshd 74 tcpdump 72 dbus 81
实例2、去知足一个或两个条件的结果 ||
[root@centos6 ~]#awk -F: '$3>=50 || $3<=100{print $1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10 operator 11 games 12 gopher 13 ftp 14 nobody 99 vcsa 69 saslauth 499 postfix 89 sshd 74 lin 500 tcpdump 72 hacker 501 dbus 81 test 502 apache 48
经常使用于只有两种状况下的判断,若是状况过多,将不适合使用三目表达式来选择
语法:判断条件?条件为真时执行语句:条件为假时执行语句
实例1、将系统中全部用户根据UID统计是系统用户仍是普通用户
[root@centos6 ~]#awk -F: '{$3>=500?usertype="common user":usertype="system user";print usertype,$1}' /etc/passwd #根据UID判断当前系统中全部用户是系统用户仍是普通用户 system user root system user bin system user daemon system user adm system user lp system user sync system user shutdown system user halt system user mail system user uucp system user operator system user games system user gopher system user ftp system user nobody system user vcsa system user saslauth system user postfix system user sshd common user lin system user tcpdump common user hacker system user dbus common user test system user apache
该模式下也支持扩展正则表达式,支持模糊搜索
1.若是未指定,空模式,匹配每一行,默认搜索每一行
实例一
[root@centos6 ~]#awk '{print $0}' /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
2./指定匹配字符/:仅处理可以模式匹配到的行须要用 / / 括起来,若匹配的行关键字中也有/则须要使用\/来转译
实例1、只有知足root为行首的行才会被匹配
[root@centos6 ~]#awk '/^root/{print $0}' /etc/passwd #表示只匹配root为行首的行。 root:x:0:0:root:/root:/bin/bash
实例2、只要知足r..o条件的将所有匹配
[root@centos6 ~]#awk '/r..t/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
3.关系表达式,若果为真才会被处理,
真:结果为非0值或非空值
假:结果为空字符串或0值
实例1、若条件为0或者空值时,则不会输出任何结果
[root@centos6 ~]#awk '0{print}' /etc/passwd
实例2、若条件为非0或控制时,则打印结果
[root@centos6 ~]#awk '1{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
实例3、该表达式中,由于awk自带行间的循环,又由于非空为1,当第一次非空则将赋值1给i则有结果输出,第二次则将一个非1则为0,将0赋给i则第二个不输出,依次类推则输出结果以下
[root@centos6 ~]#seq 10 | awk 'i=!i' 1 3 5 7 9
4.行范围,awk也能取匹配字符的行范围 /匹配字符1/,/匹配字符2/处理动做
[root@centos6 ~]# awk '/^h/,/^f/' /etc/passwd halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin hacker:x:501:501::/home/hacker:/bin/bash dbus:x:81:81:System message bus:/:/sbin/nologin test:x:502:502::/home/test:/bin/bash apache:x:48:48:Apache:/var/www:/sbin/nologin
当遇到以h为行首的行,则打印,到行首为f结束,由于打印完以后有碰到h为行首,则继续打印,由于后面没有h为行首,则一直打印到就结束
5.BEGIN/END模式
BEGIN{}:仅在开始处理文本以前执行一次
BEGIN属于在文本执行前执行的语句块,它不依赖于任何文件或输出结果
[root@centos6 ~]#awk 'BEGIN{print "test"}' test
END{}:仅在文本处理完成以后执行一次
END工做在awk处理完文本以后执行一次。能够用于打印pattern语句块执行过程的结果
它也依赖于文件或输出结果
[root@centos6 ~]#awk 'END{print "test"}' /etc/passwd test
1.if else
语法
if(判断条件){知足条件执行的语句} [else {不知足条件执行语句} if(判断条件1){知足条件1执行语句}else if (判断条件2{知足条件2时执行语句}else{不 知足上述两个条件执行语句]
实例1、根据UID判断系统中用户是系统用户仍是普通用户
[root@centos6 ~]#awk -F: '{if($3<=200){name="system"}else {name="user"} print $1,name}' /etc/passwd root system bin system daemon system adm system lp system sync system shutdown system halt system mail system uucp system operator system games system gopher system ftp system nobody system vcsa system saslauth user postfix system sshd system lin user tcpdump system hacker user dbus system test user apache system
实例2、将20到30的数相加
[root@centos6 ~]#seq 50 |awk '{if($1>=20&&$1<=30){sum+=$1}}END{print sum}' 275
判断系统中小于300的所有都是系统用户,其余的所有为普通用户
2.while循环
语法{while (判断条件){循环语句}},条件为真时,开始执行循环
awk属于行之间的循环,他不会对列进行循环,因此若须要对列进行计算和格式化处理,则须要使用awk内置循环来进行
实例1、将每一行的和输出值终端
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{sum=0;i=1;while(i<=NF){sum+=$i ;i++}print sum}' test.txt 55 155
实例2、统计/boot/grub2/grub.conf文件中行首为linux16行每个字段的字符数
[root@centos7 ~]# awk '/^[[:space:]]+linux/{i=1;while(i<=NF){print $i,length($i);i++}}' /boot/grub2/grub.cfg linux16 7 /vmlinuz-0-rescue-e8e8f687a3b24f13bda5566ae49855e6 50 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 linux16 7 /vmlinuz-4.15.13.test 21 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 LANG=en_US.UTF-8 16
i做为自增项,循环条件为i<=字段数,length($i)内置函数,用于测量字段的长度
3.do while
语法
do{循环语句}while(判断条件),该语句与while惟一不一样就是循环必定执行一次,无论判断条件是否为真
4.for循环
语法
for(变量;判断;变量自增){循环语句},其中()中必须是三部分组成
实例1、该实例和while实现的功能一直,只是写法不一样
[root@centos7 ~]# awk '/^[[:space:]]+linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /boot/grub2/grub.cfg linux16 7 /vmlinuz-0-rescue-e8e8f687a3b24f13bda5566ae49855e6 50 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 linux16 7 /vmlinuz-4.15.13.test 21 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 LANG=en_US.UTF-8 16
break:直接跳出循环
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{for(i=1;i<=NF;i++){if($i%2==0){break}print $i}}' test.txt 1 11
由于当前文件中有两行内容,则显示两个数,若是只有一行内容,则只显示第一个数,由于当执行到2的时候跳出循环进入下次循环,而11之后则是下次循环,因此还会继续执行
continue:退出此次循环,进入下次循环、
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{for(i=1;i<=NF;i++){if($i%2==0){continue}print $i}}' test.txt 1 3 5 7 9 11 13 15 17 19
当$i的值除以2 余数为0则跳出循环,其余则输出
next:跳出当前行循环,进入下次行循环
[root@centos6 ~]#seq 10 |awk '{if($1%2==0){next}print $1}' 1 3 5 7 9
next控制的是行间的调过,当该行知足这个条件,则跳出这行循环,进入下次循环
awk中的数组只有关联数组
1.可使用任意字符串,字符串要使用双引号括起来
2.若是某数组元素实现不存在,在引用时,awk会自动建立次元素,并将其值初始化为空字符串
语法
数组名["下标"]="参数"
数组能够用于统计某个字符串出现过几回,用来统计次数
实例1、统计access_log文件每个ip的访问次数
[root@centos6 ~]#awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access_log 172.18.250.183 81 172.18.251.149 158 172.18.0.223 12 172.18.251.21 81 172.18.251.122 52 172.18.254.6 1643 172.18.253.21 74087 172.18.251.150 34 172.18.252.134 514
length():返回指定字符串的长度
[root@centos6 ~]#echo abcde | awk '{print length($1)}' 5
rand():返回0和1之间的随机数,也就是小数在使用rand()函数时,在前面必须指定种子srand(),若想随机整数,则须要乘以一个数(根据想要的位数)[root@centos6 ~]#awk 'BEGIN{srand();print int(rand()*10)}'
int()也是函数,它的做用是取整数,当前命令会随机取10之内的整数
sub(r,s,[t]):对t字符串进行搜索r表示模式匹配的内容,并将第一个匹配的内容替换为s
gsub(r,s,[t]):对匹配的字符全局替换
[root@centos6 ~]#echo {1..10} | awk 'gsub(" ",":",$0)' 1:2:3:4:5:6:7:8:9:10
将空格全局替换成:
split(s,array,[r]):以r为分隔符,切割字符串s,而且将切割后的结果保存到array的数组中,第一个索引值为1
[root@centos6 ~]#awk '{split($5,c,":")};{ip[c[1]]++}END{for (i in ip){print $1,ip[i]}}' netstat.log tcp 13 tcp 3 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 15
function name (虚变量1,虚变量2){ 处理动做 处理动做 }
虚变量指的是须要用户输入两个变量,可是传入函数执行的变量和函数自己变量名不一致,也能够理解成一种定义格式,必须指定两个变量才能够调用该函数
awk程序也能够写成脚本,而后当程序须要是,能够直接调用执行,awk脚本也是须要执行权限,因此在执行以前须要个执行权限
脚本格式
#!/bin/awk -f 脚本内容
实例一
#!/bin/awk -f function biji (x,y){ if(x>y){ max="x>y"} else if (x==y){max="x=y"} else{ max="x<y" } return max } BEGIN{print biji(a,b)} [root@centos6 ~]#awk -v a=7 -v b=7 -f test.awk x=y [root@centos6 ~]#awk -v a=7 -v b=6 -f test.awk x>y [root@centos6 ~]#awk -v a=5 -v b=6 -f test.awk x<y
在awk语句中,也能够根据需求调用系统的一些命令,可是要结合system内置函数来实现
语法awk BEGIN‘system("系统命令")’