虚拟化容器,大数据,DBA,中间件,监控。

Shell 四剑客AWK第一集

21 12月
作者:admin|分类:脚本编程

AWK简介


AWK是一个优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一,以Aho、Weinberger、Kernighan三位发明者名字首字母命名为AWK,AWK是一个行级文本高效处理工具,AWK经过改进生成的新的版本有Nawk、Gawk,一般Linux默认为Gawk,Gawk是 AWK的GNU开源免费版本。

和 sed 命令类似,awk 命令也是逐行扫描文件(从第 1 行到最后一行),寻找含有目标文本的行,如果匹配成功,则会在该行上执行用户想要的操作;反之,则不对行做任何处理。

AWK基本原理是逐行处理文件中的数据,查找与命令行中所给定内容相匹配的模式,如果发现匹配内容,则进行下一个编程步骤,如果找不到匹配内容,则继续处理下一行。其语法参数格式为,AWK常用参数、变量、函数详解如下:

Awk     'pattern   +   {action}'     file

 

AWK基本语法参数详解:


  1. 单引号' '是为了和shell命令区分开;
  2. 大括号{ }表示一个命令分组;
  3. pattern是一个过滤器,表示匹配pattern条件的行才进行Action处理;
  4. action是处理动作,常见动作为Print;
  5. 使用#作为注释,pattern和action可以只有其一,但不能两者都没有。

 

AWK内置变量详解:


  1. FS 分隔符,默认是空格;
  2. OFS 输出分隔符;
  3. NR 当前行数,从1开始;
  4. NF 当前记录字段个数;
  5. $0 当前记录;
  6. $1~$n 当前记录第n个字段(列)。

 

AWK举例说明


 打印你需要的列 $0|$n|$NF

//打印出文件的内容。这个和cat score.txt是一样的,$0是当前记录
[root@vagrant-centos65 awk]# awk '{print $0}' score.txt
Aaron    Physics    87
Abel     Maths      98
Rahul    Chinese    90
Buck     Biology    87
Byron    English    85
Dave     History    89
Enoch    Chemistry  89

//打印出第一列。
[root@vagrant-centos65 awk]# awk '{print $1}' score.txt
Aaron
Abel
Rahul
Buck
Byron
Dave
Enoch

//打印出最后一列,最后一列是使用NF来表示的。
[root@vagrant-centos65 awk]# awk '{print $NF}' score.txt
87
98
90
87
85
89
89

打印你需要要的行 NR,END

//将行号打印出来,通过变量NR,NR在AWK里面代表行号
[root@www ~]# awk  '{print NR,$1,$2,$3}' socre.txt #a等价awk  '{print NR,$0}' socre.txt 
1 Aaron Physics 87
2 Abel Maths 98
3 Rahul Chinese 90
4 Buck Biology 87
5 Byron English 85
6 Dave History 89
7 Enoch Chemistry 89
[root@www ~]# awk  '{print NR" ",$0}' socre.txt   #加了一个空格“ ”,这样更加美观
1  Aaron    Physics    87
2  Abel     Maths      98
3  Rahul    Chinese    90
4  Buck     Biology    87
5  Byron    English    85
6  Dave     History    89
7  Enoch    Chemistry  89

//打印出第一行。
[root@localhost ~]# awk 'NR==1 {print NR" ",$0}' score.txt 
1  Aaron    Physics    87

//打印偶数行
[root@localhost ~]# awk 'NR%2==0  {print NR" ",$0}' score.txt 
2  Abel     Maths      98
4  Buck     Biology    87
6  Dave     History    89

//打印奇数行
[root@www ~]# awk 'NR%2!=0 {print NR " ",$1,$2,$3 }' socre.txt  #或者NR%2==1也一样
1  Aaron Physics 87
3  Rahul Chinese 90
5  Byron English 85
7  Enoch Chemistry 89

//打印出最后一行。
[root@vagrant-centos65 awk]# awk 'END{print}' score.txt
Enoch    Chemistry  89
//打印最后一行的行号
[root@localhost ~]# awk 'END{print NR}' score.txt 
7

//打印出指定行的指定列。比如 第四行第二列
[root@vagrant-centos65 awk]# awk 'NR==4{print $2}' score.txt
Biology

//打印二到三行的第一列
[root@www ~]# awk  'NR==1,NR==3 {print $1}' socre.txt 
Aaron
Abel
Rahul
[root@www ~]# awk  'NR>=1&&NR<=3 {print $1}' socre.txt #和上面方式一样
Aaron
Abel
Rahul

通过//匹配行,再打印列 

[root@localhost ~]# cat score.txt 
Aaron    Physics    87
Abel     Maths      98
Rahul    Chinese    90
Buck     Biology    87
Byron    English    85
Dave     History    89
Enoch    Chemistry  89

//打印出匹配的行
[root@localhost ~]# awk '/Chinese/' score.txt    
Rahul    Chinese    90

//行开头匹配。
[root@vagrant-centos65 awk]# awk '/^A/' score.txt
Aaron    Physics    87
Abel     Maths      98

[root@vagrant-centos65 awk]# awk '/^B/' score.txt
Buck     Biology    87
Byron    English    85


//行结束匹配。
[root@vagrant-centos65 awk]# awk '/89$/' score.txt
Dave     History    89
Enoch    Chemistry  89

//通过匹配模式匹配到行再打印列
[root@localhost ~]# awk '/Chinese/{print $1,$3}' score.txt 
Rahul 90

 需要打印美观,可以如下

//如果要修饰你打印出来的结果可以使用双引号"",这种例子可以获取IP的网关
[root@www ~]# awk '{print $1"."$2"."$3".mytest"}' socre.txt 
Aaron.Physics.87.mytest
Abel.Maths.98.mytest
Rahul.Chinese.90.mytest
Buck.Biology.87.mytest
Byron.English.85.mytest
Dave.History.89.mytest
Enoch.Chemistry.89.mytest
[root@www ~]# echo 192.168.179.100 | awk -F. '{ print "the gate way is:"  $1"."$2"."$3}'
the gate way is:192.168.179
[root@www ~]# awk '{print "student test score:"$1"."$2"."$3}' socre.txt 
student test score:Aaron.Physics.87
student test score:Abel.Maths.98
student test score:Rahul.Chinese.90
student test score:Buck.Biology.87
student test score:Byron.English.85
student test score:Dave.History.89
student test score:Enoch.Chemistry.89

-F以不同的方式分割

#以:分割
[root@www ~]# cat /etc/passwd | head -n 3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@www ~]# cat /etc/passwd | head -n 3 | awk -F: '{print $1}' 
root
bin
Daemon


#以root做分隔符
[root@www ~]# cat a.test 
192.168.179.99  root  123
192.168.179.100 root 123456
192.168.179.101 root  1234     
[root@www ~]# awk -F'root'  '{print $1}' a.test  
192.168.179.99  
192.168.179.100 
192.168.179.101 
[root@www ~]# awk -F'root'  '{print $2}' a.test 
  123
 123456
  1234  



#以http://   //切割
[root@www ~]# cat a.test 
http://www.baidu.com
http://www.qq.com
http://www.test.net

[root@www ~]# awk -F'http://' '{print $2}' a.test --取域名,这里是打印第二列,不是第一列,因为截取的时候产生了空格
www.baidu.com
www.qq.com
www.test.net

[root@www ~]# awk -F'//' '{print $1}' a.test --按照这种方法就不存在空格问题
http:
http:
http:
[root@www ~]# awk -F'//' '{print $2}' a.test 
www.baidu.com
www.qq.com
www.test.net


#如果是多个条件加上中括号,一个条件就不需要,比如上面例子
-F’abcd’是按abcd字符串来切割
-F‘[abcd]’是按照a,b,c,d一个一个来切割

[root@www ~]# awk -F'[:.]' '{print $1}' a.test --按照:和.切割
http
http
http
[root@www ~]# awk -F'[:.]' '{print $2}' a.test 
//www
//www
//www
[root@www ~]# awk -F'[:.]' '{print $3}' a.test 
baidu
qq
Test


[root@www ~]# cat /etc/passwd | head -n 3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin


[root@localhost ~]# awk -F: 'NR==3 {print $1}' sed.sh  打印第三行第一列
daemon
[root@localhost ~]# awk -F: 'NR==1,NR==3 {print $1}' sed.sh  使用NR来指定打印第几行
root
bin
Daemon

NF NF-1 倒数列

[root@localhost ~]# cat score.txt 
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

#打印最后一列
[root@localhost ~]# awk -F: '{print $NF}' score.txt 
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
#打印倒数第二列
[root@localhost ~]# awk -F: '{print $(NF-1)}' score.txt 
/root
/bin
/sbin
/var/adm
/var/spool/lpd
#打印倒数第三列
[root@localhost ~]# awk -F: '{print $(NF-2)}' score.txt 
root
bin
daemon
adm
lp
[root@www ~]# cat socre.txt 
Aaron    Physics    87
Abel     Maths      98
Rahul    Chinese    90
Buck     Biology    87
Byron    English    85
Dave     History    89
Enoch    Chemistry  89
[root@www ~]# awk '{sum+=$3}{print sum}' socre.txt 
87
185
275
362
447
536
625
[root@www ~]# awk '{sum+=$3}END{print sum}' socre.txt  #可以看到awk里面变量的调用时不需要加$符号的
625

//条件判断输出,注意使用if要使用{},将if print看作整体
[root@www ~]# echo 3 2 1 | awk '{if (($1>$2)) print $1 }'
3
[root@www ~]# echo 0 2 1 | awk '{if (($1>$2)) {print $1} else {print $3} }'
1
[root@www ~]# echo 3 2 1 | awk '{if(($1>$2)||($2>$3)) {print $1} else {print$3}}'
3

 

awk分析Nginx访问日志的状态码404、502等错误信息页面,统计次数大于20的IP地址。

awk '{if ($9~/502|499|500|503|404/) print $1,$9}' access.log|sort|uniq –c|sort –nr | awk '{if($1>20) print $2}'
或者
awk '$9~/502|499|500|503|404/ {print $1,$9}' access.log|sort|uniq –c|sort –nr | awk '{if($1>20) print $2}'
分解如下:
[root@www ~]# cat socre.txt 
Aaron    Physics    87
Abel     Maths      98
Rahul    Chinese    90
Buck     Biology    87
Byron    English    85
Dave     History    89
Enoch    Chemistry  89
//将第三列匹配到的87,98,85整行打印出来
[root@www ~]# awk '{if ($3~/87|98|85/) print $0}' socre.txt 
Aaron    Physics    87
Abel     Maths      98
Buck     Biology    87
Byron    English    85
[root@www ~]# awk '{if ($NF~/87|98|85/) print $0}' socre.txt  #和上面一样使用$NF代表最后一列
Aaron    Physics    87
Abel     Maths      98
Buck     Biology    87
Byron    English    85
[root@www ~]# awk '$NF~/87|98|85/ {print $0}' socre.txt 
Aaron    Physics    87
Abel     Maths      98
Buck     Biology    87
Byron    English    85



Awk统计服务器状态连接数:
netstat -an | awk '/tcp/ {print $NF}' | sort | uniq -c

分解过程如下:
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}'
LISTEN
LISTEN
LISTEN
ESTABLISHED
LISTEN
LISTEN
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort #排序将相同的放一起
ESTABLISHED
LISTEN
LISTEN
LISTEN
LISTEN
LISTEN
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq
ESTABLISHED
LISTEN
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq -c  #-c是count统计次数,分组统计次数
      1 ESTABLISHED
      5 LISTEN
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq -c | sort -n #正向排序
      1 ESTABLISHED
      5 LISTEN
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq -c | sort -nr #逆向排序
      5 LISTEN
      1 ESTABLISHED

[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq -c | sort -nr | awk '{print $1}'
5
1
[root@www ~]# netstat -na | awk '/^tcp/ {print $NF}' |sort | uniq -c | sort -nr | awk '{if($1>1) print $1}'
5

 

浏览570 评论0
返回
目录
返回
首页
Shell 四剑客之 grep高效查找 Shell 四剑客之 sed a i 添加新行