AWK

一、AWK之入门

1.AWK简介

AWK并非是一个简单的命令,他其实是一门编程语言,非常适合用来处理文本类数据。数据可以来自标准输入、外部文件,或者其他命令的输出。AWK同时支持正则表达式和用户自定函数。

2.AWK的语法格式

awk 'Pattern {Action}' filename
-其中Pattern用来指定判断条件
-{}中包含的是awk的动作,也就是awk对记录的操作

3.AWK的工作原理

step1:
AWK读取一条记录在作为输入,并将这条记录赋值给内部变量$0
step2:
记录被分隔符分隔成了多个字段,每个字段都存储到指定编号的变量中,从$1开始
step3:
对于每一条记录按照指定的Pattern进行匹配,如果匹配成功,则执行相应的Action
step4:
重复1~3,直到文件结束

4.AWK最简单入门

  • AWK的处理单位是:行 –> $0是一个特殊符号,他表示的正是一行的内容
    例1:假如有一个文件test.txt,我们想要输入文件的内容
[kiosk@foundation8 关键知识点]$ cat test.txt 
huangxin100   2014/12/03
huangxin101   2015/05/06
huangxin102   2016/06/04
huangxin103   2017/03/05

[kiosk@foundation8 关键知识点]$ awk '{print $0}' test.txt 
huangxin100   2014/12/03
huangxin101   2015/05/06
huangxin102   2016/06/04
huangxin103   2017/03/05

例2:指定输出列

[kiosk@foundation8 关键知识点]$ cat test.txt
huangxin100   2014/12/03
huangxin101   2015/05/06
huangxin102   2016/06/04
huangxin103   2017/03/05

[kiosk@foundation8 关键知识点]$ awk '{print $1}' test.txt 
huangxin100
huangxin101
huangxin102
huangxin103

[kiosk@foundation8 关键知识点]$ awk '{print $2}' test.txt 
2014/12/03
2015/05/06
2016/06/04
2017/03/05

[kiosk@foundation8 关键知识点]$ awk '{print $1,$2}' test.txt 
huangxin100 2014/12/03
huangxin101 2015/05/06
huangxin102 2016/06/04
huangxin103 2017/03/05

例3:修饰表头和表尾

[kiosk@foundation8 关键知识点]$ awk 'BEGIN {print "  NAME         BIRTHDAY\n--------------------------"}{print $0} END {print "--------------------------"}' test.txt 
  NAME         BIRTHDAY
--------------------------
huangxin100   2014/12/03
huangxin101   2015/05/06
huangxin102   2016/06/04
huangxin103   2017/03/05

--------------------------

例4:统计

[kiosk@foundation8 关键知识点]$ cat test.txt 
huangxin100   2014/12/03   23   79
huangxin101   2015/05/06   25   56
huangxin102   2016/06/04   56   56 
huangxin103   2017/03/05   89   23

[kiosk@foundation8 关键知识点]$ awk 'BEGIN {print "  NAME      BIRTHDAY   total\n-------------------------------"}{print $1,$2,$3+$4} END {print "-------------------------------"}' test.txt 
  NAME      BIRTHDAY   total
-------------------------------
huangxin100 2014/12/03 102
huangxin101 2015/05/06 81
huangxin102 2016/06/04 112
huangxin103 2017/03/05 112
-------------------------------

例5:筛选
筛选出huangxin100的信息

[kiosk@foundation8 关键知识点]$ awk 'BEGIN {print "  NAME      BIRTHDAY   total\n-------------------------------"} $1 ~ /huangxin100/ {print $1,$2,$3+$4} END {print "-------------------------------"}' test.txt 
  NAME      BIRTHDAY   total
-------------------------------
huangxin100 2014/12/03 102
-------------------------------

例6:像编脚本一样编awk

[kiosk@foundation8 关键知识点]$ awk -f test.awk test.txt 
  NAME      BIRTHDAY   total
-------------------------------
huangxin100 2014/12/03 102
huangxin101 2015/05/06 81
huangxin102 2016/06/04 112
huangxin103 2017/03/05 112
-------------------------------

[kiosk@foundation8 关键知识点]$ cat test.awk 
BEGIN {print "  NAME      BIRTHDAY   total\n-------------------------------"} 
{print $1,$2,$3+$4} 
END {print "-------------------------------"}

[kiosk@foundation8 关键知识点]$ cat test.txt 
huangxin100   2014/12/03   23   79
huangxin101   2015/05/06   25   56
huangxin102   2016/06/04   56   56 
huangxin103   2017/03/05   89   23

例6(+):加上环境变量,看起来更像脚本

[kiosk@foundation8 Desktop]$ cat test.awk 
#!/bin/awk -f
BEGIN {print "  NAME      BIRTHDAY   total\n-------------------------------"} 
{print $1,$2,$3+$4} 
END {print "-------------------------------"}

[kiosk@foundation8 Desktop]$ cat test.txt 
huangxin100   2014/12/03   23   79
huangxin101   2015/05/06   25   56
huangxin102   2016/06/04   56   56 
huangxin103   2017/03/05   89   23

[kiosk@foundation8 Desktop]$ ./test.awk test.txt 
  NAME      BIRTHDAY   total
  -------------------------------
  huangxin100 2014/12/03 102
  huangxin101 2015/05/06 81
  huangxin102 2016/06/04 112
  huangxin103 2017/03/05 112
  -------------------------------

二、AWK之多行操作

例1:只展示奇数行

[kiosk@foundation8 关键知识点]$ cat test.txt 
1
2
3
4
5
6
7
8
9

[kiosk@foundation8 关键知识点]$ awk 'NR%2==0 {next} {print NR, $0}' test.txt 
1 1
3 3
5 5
7 7
9 9

例2:固定行数合并

[kiosk@foundation8 关键知识点]$ cat test.txt 
1
2
3
4
5
6
7
8
9

[kiosk@foundation8 关键知识点]$ awk 'NR%3!=0 {T=(T" "$0);next} {print T, $0;T=""} END {print T}' test.txt 
 1 2 3
 4 5 6
 7 8 9

例3:不定行数合并

[kiosk@foundation8 关键知识点]$ cat test.txt 
xiaoming grade is 
12
45
89
36
46
xiaohong grade is 
13 
46
79
12
23
xiaoqiang grade is 
12 
56
79
46
46

使用正着表达式来进行分组:/grade/
问题:没有将后面的数字分开

[kiosk@foundation8 关键知识点]$ awk 'BEGIN {T=""} /grade/ {print T; T=$0; next} {T=T""$0} END {print T}' test.txt 

xiaoming grade is 1245893646
xiaohong grade is 13 46791223
xiaoqiang grade is 12 56794646

例4:合并所有行

[kiosk@foundation8 关键知识点]$ cat test.txt 
one
two
three
four
five
six
seven
eight
nine
ten

[kiosk@foundation8 关键知识点]$ awk '{T=T" "$0} END {print T}' test.txt 
 one two three four five six seven eight nine ten

三、AWK之多文件操作

例1:多文件输出

[kiosk@foundation8 关键知识点]$ cat input1.txt 
hello

[kiosk@foundation8 关键知识点]$ cat input2.txt 
world

[kiosk@foundation8 关键知识点]$ awk '{print $0}'  input1.txt input2.txt 
hello
world

例2:两手抓两个文件

[kiosk@foundation8 关键知识点]$ cat input1.txt 
hello1
world1
[kiosk@foundation8 关键知识点]$ cat input2.txt 
hello2
world2

要求:抓出文件一的第一行,文件二的第二行,以及相应的名字

[kiosk@foundation8 关键知识点]$ awk 'NR==FNR&&FNR==1 {print FILENAME,    $0} NR>FNR&&FNR==2 {print FILENAME,$0}' input1.txt input2.txt 
input1.txt hello1
input2.txt world2

例3:多只手抓多个文件

[kiosk@foundation8 关键知识点]$ cat input1.txt 
hello1
world1
[kiosk@foundation8 关键知识点]$ cat input2.txt 
hello2
world2
[kiosk@foundation8 关键知识点]$ cat input3.txt 
hello3
world3 
!!!

要求:显示input1.txt的第一行,input2.txt的第二行,input3.txt的第三行

<方法一>
[kiosk@foundation8 关键知识点]$ awk 'ARGIND==1&&FNR==1 {print $0} ARGIND==2&&FNR==2 {print $0} ARGIND==3&&FNR==3 {print $0}' input1.txt input2.txt input3.txt 
hello1
world2
!!! 

<方法二>
[kiosk@foundation8 关键知识点]$ awk 'FILENAME==ARGV[1]&&FNR==1 {print $0} FILENAME==ARGV[2]&&FNR==2 {print $0} FILENAME==ARGV[3]&&FNR==3 {print $0}' input1.txt input2.txt input3.txt 
hello1
world2
!!! 

例四:合并两个文件

Linux系统中有两个很特殊的文件,分别为:/etc/passwd 和 /etc/shadow
/etc/passwd:

[kiosk@foundation8 关键知识点]$ head  /etc/passwd   --> 第二个域用x代替,存储的是账户对应的密码
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

/etc/shadow:
[root@foundation8 关键知识点]# head /etc/shadow    
root:$6$oZ1JGQiQ$0lau6DEHSV81iQ54SJyjhI7s9DvAz2Ly5JVwGxMXJqDodk61DXZnF79ibX.scEeHKIe1tBTqLSCIfYV2k3AuW1::0:99999:7:::
bin:*:16925:0:99999:7:::
daemon:*:16925:0:99999:7:::
adm:*:16925:0:99999:7:::
lp:*:16925:0:99999:7:::
sync:*:16925:0:99999:7:::
shutdown:*:16925:0:99999:7:::
halt:*:16925:0:99999:7:::
mail:*:16925:0:99999:7:::
operator:*:16925:0:99999:7:::
  • 我们希望用/etc/shadow文件中的密码替换掉/etc/passwd中的”x”,生成一个全新的passwd文件
[root@foundation8 关键知识点]# awk 'BEGIN {OFS=FS=":"} NR==FNR {a[$1]=$2} NR>FNR {$2=a[$1]; print} ' shadow passwd
root:$6$oZ1JGQiQ$0lau6DEHSV81iQ54SJyjhI7s9DvAz2Ly5JVwGxMXJqDodk61DXZnF79ibX.scEeHKIe1tBTqLSCIfYV2k3AuW1:0:0:root:/root:/bin/bash
bin:*:1:1:bin:/bin:/sbin/nologin
daemon:*:2:2:daemon:/sbin:/sbin/nologin
adm:*:3:4:adm:/var/adm:/sbin/nologin
lp:*:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:*:5:0:sync:/sbin:/bin/sync
shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown
halt:*:7:0:halt:/sbin:/sbin/halt
mail:*:8:12:mail:/var/spool/mail:/sbin/nologin
operator:*:11:0:operator:/root:/sbin/nologin
[root@foundation8 关键知识点]# 

例五:合并两个文件并求合

[root@foundation8 关键知识点]# cat -n 1.txt 
     1  56 23 46
     2  56 79 13
[root@foundation8 关键知识点]# cat -n 2.txt 
     1  56 23 46
     2  56 79 13

[root@foundation8 关键知识点]# awk '{for(i=1;i<=NF;i++) a[i]=$i; getline<"1.txt";for(i=1;i<=NF;i++) printf a[i]+$i" ";printf "\n"}' 2.txt
112 46 92 
112 158 26 

四、AWK之外部调用

实现awk外部调用的两种方式:

  • 通过getline引用外部数据
  • 通过system调用Shell中的命令

例一:getline操作文件中的困惑

1){print;getline}输出的是文件的奇数行
[kiosk@foundation8 关键知识点]$ awk '{print;getline}' test
one
three
five

2){getline;print}输出的是文件的偶数行
[kiosk@foundation8 关键知识点]$ awk '{getline;print}' test
two
four
six

3){getline;print;getline}输出的是文件的全部内容
[kiosk@foundation8 关键知识点]$ awk '{print;getline;print}' test
one
two
three
four
five
six

4){print;getline b;print}重复输出奇数行
[kiosk@foundation8 关键知识点]$ awk '{print;getline b;print}' test
one
one
three
three
five
five

[kiosk@foundation8 关键知识点]$ awk '{print;getline b;print;print b}' test
one
one
two
three
three
four
five
five
six
  • 原因如下:getline获取的是下一行的内容;getline后面跟一个变量,表示获取的数据不会复制给$0,而会给这个变量

例2:getline操作文件的返回值

[kiosk@foundation8 关键知识点]$ cat 1.txt 
56 23 46
56 79 13
[kiosk@foundation8 关键知识点]$ cat test
one
two
three
four
five
six

[kiosk@foundation8 关键知识点]$ awk '{print $0; while((getline<"1.txt")>0) print $0}' test
one
56 23 46
56 79 13
two
three
four
five
six

需要解释的几点:

1>getline的返回值:
- 1:表示正常读取一行数据
- 0:表示到了文件末尾
- -1:表示读取遇到麻烦

2>getline重定向文件时,后面必须跟字符串类型。因此,1.txt必须加双引号,否则,awk是不会认为他是文件名的

例2:用system调用Shell

[kiosk@foundation8 关键知识点]$ awk 'BEGIN { system("ls -al")}'
total 296
drwx------ 13 kiosk kiosk  8192 Jan 15 19:09 .
drwx------ 10 kiosk kiosk 16384 Jan  1  1970 ..
-rw-r--r--  1 kiosk kiosk    18 Jan 15 18:58 1.txt
-rw-r--r--  1 kiosk kiosk    18 Jan 15 18:58 2.txt
-rw-r--r--  1 kiosk kiosk     9 Jan 13 23:40 callsed
drwx------  2 kiosk kiosk  8192 Jan 13 11:09 docker
-rw-r--r--  1 kiosk kiosk    43 Jan 14 01:02 fstab
-rw-r--r--  1 kiosk kiosk     0 Jan 14 00:15 Git工具
-rw-r--r--  1 kiosk kiosk    14 Jan 15 01:03 input1.txt
-rw-r--r--  1 kiosk kiosk    14 Jan 15 01:04 input2.txt
-rw-r--r--  1 kiosk kiosk    19 Jan 15 18:37 input3.txt
-rw-r--r--  1 kiosk kiosk    20 Jan 13 23:46 ins.txt

注意两点:

1>awk无法直接将脚本中的数据直接输出给shell命令
2>shell命令的执行结果也无法直接输出到awk脚本中

五AWK之实战

例1:显示本机的IP

[kiosk@foundation8 关键知识点]$ ifconfig | awk '/^br/ {inter=$1;getline;print inter,$2}'
br0: 172.25.8.250

例2:统计网卡的流量

例3:查看TCP连接状态

[root@foundation8 Desktop]# netstat -nat | awk '{print $6}'| sort |uniq -c |sort -rn
     10 LISTEN
      1 Foreign
      1 established)

例4:查找请求数排名前5名的IP地址

例5:用tcpdump嗅探80端口的访问

例5:锁定time_wait链接最多的源IP

例6:根据端口列进程

[root@foundation8 kiosk]# netstat -ntlp | grep 80 | awk  '{print $7}' | cut -d/ -f1
1348

学习资源:大鹏Linux命令百篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值