awk用法详解

1、awk介绍

  awk是文本三剑客之一,其实awk是一种语言,该语言的创始者定义为”生成报表和格式化文本输出“awk有不少种版本,这里介绍的是GUN awk(gawk)linux

2、awk工做原理

  第一步:执行BEGIN{action}语句块中的语句,该语句块不依赖于文件,awk在执行是,将在读取文件以前执行该语句中的语句块,经常使用语变量的初始化,打印输出表格的表头。
  第二步:从文件、标准输入、上一条命令输出结果输入地区一行,而后进行pattern{aciton}语句块,它将逐行扫描文件,从第一行到最后一行。若没有提供pattern语句,则默认执行打印{print},即打印每个读取到的行。
  第三步:当读至文件最后时,执行END{action}语句块。一般用于汇总在pattern语句中执行的过程正则表达式

3、awk基本用法

选项
-F"指定分隔符"
-v 自定义变量:定义变量
      
awk {print} file
awk将把file文件中的每一行都读取一遍,而后输出在终端上
输入内置变量在文本中表明以下图所示
awk用法详解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 ~]#  

awk用法详解
实例一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

4、awk内置变量

  awk命令的print打印内容也能够不与文件有关,若没有关系,则表示文件有多少行内容,就会打印本身所指定的内容,而在awk中,处理动做中的字母若不用" "引上则表示使用变量,因此若须要输出字符串则须要用“ ”引上。数字则不须要。
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

5、printf格式化输出

  在输出内容时,print输出只能输出规定格式的内容,不能自定义格式,因此想要让输出结果根据本身所须要的格式输出就须要用printf来定制格式
printf使用格式
awk ‘{printf "格式1 格式 ",$1,$2}’,格式必须和须要输出的列一一对应
awk用法详解
实例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

6、awk运算符

  awk也能够进行数字间的运算,不但支持整数,并且支持小数
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

7、赋值运算

在赋值操做符中,sum+=i,就至关于sum=sum+i,
awk用法详解
实例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变量将自增几回

8、模式匹配

  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

  因所搜内容中也包含 ” / “ 因此须要将搜索内容用双引号引发来

9、比较操做符

awk用法详解

10、逻辑操做符

&&:表示同时知足两个条件
||:表示知足两个条件中的一个便可
!:表示取匹配结果的反值
实例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

11、条件表达式(三目表达式)

  经常使用于只有两种状况下的判断,若是状况过多,将不适合使用三目表达式来选择
语法:判断条件?条件为真时执行语句:条件为假时执行语句
实例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

12、PATTERN模式搜索

  该模式下也支持扩展正则表达式,支持模糊搜索
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

十3、awk控制语句

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

十3、循环控制语句

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控制的是行间的调过,当该行知足这个条件,则跳出这行循环,进入下次循环

十3、awk数组

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

十4、awk内置函数

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

十5、awk自定义函数,脚本调用

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

十6、system命令

  在awk语句中,也能够根据需求调用系统的一些命令,可是要结合system内置函数来实现
语法
awk BEGIN‘system("系统命令")’

相关文章
相关标签/搜索