Shell 四剑客AWK第一集
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基本语法参数详解:
- 单引号' '是为了和shell命令区分开;
- 大括号{ }表示一个命令分组;
- pattern是一个过滤器,表示匹配pattern条件的行才进行Action处理;
- action是处理动作,常见动作为Print;
- 使用#作为注释,pattern和action可以只有其一,但不能两者都没有。
AWK内置变量详解:
- FS 分隔符,默认是空格;
- OFS 输出分隔符;
- NR 当前行数,从1开始;
- NF 当前记录字段个数;
- $0 当前记录;
- $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
目录 返回
首页