您的位置:首页 > 运维架构 > Linux

Linux awk命令简介

2015-08-05 11:12 489 查看
        AWK是一种优良的文本处理工具,LinuxUnix环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人阿尔佛雷德·艾侯彼得·温伯格布莱恩·柯林汉姓氏的首个字母)的最大功能取决于一个人所拥有的知识。

AWK提供了极其强大的功能:可以进行

1.        正则表达式的匹配

2.        样式装入

3.        流控制

4.        数学运算符

5.        进程控制语句

6.        内置的变量和函数

        它具备了一个完整的语言所应具有的几乎所有精美特性。实际上AWK的确拥有自己的语言:AWK程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。它允许创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。gawk是AWK的GNU版本。

        最简单地说,AWK是一种用于处理文本的编程语言工具。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

 

awk命令格式:

awk  ‘条件类型1 {动作1} 
条件类型2{动作2}
……’  filename


 

内建变量

$0

一整行

$1~$n

当前记录(行)的第n个字段,字段间由FS分隔

FS

输入字段分隔符 默认是空格或Tab

NF

列数

NR

行号,从1开始,如果有多个文件话,这个值也是不断累加中。

FNR

当前记录数,与NR不同的是,这个值会是各个文件自己的行号

RS

输入的记录分隔符, 默认为换行符

OFS

输出字段分隔符, 默认也是空格

ORS

输出的记录分隔符,默认为换行符

FILENAME

当前输入文件的名字

原文件:

[root@chenchen cctmp]# cat netstat.txt
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 0 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT
tcp 0 0 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2
tcp 0 0 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED
tcp 0 0 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED
tcp 0 0 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2
tcp 0 0 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED
tcp 0 0 coolshell.cn:80 183.60.215.36:36970 TIME_WAIT
tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED
tcp 0 1 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1
tcp 0 0 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED
tcp 0 0 coolshell.cn:80 183.60.212.163:51082 TIME_WAIT
tcp 0 1 coolshell.cn:80 208.115.113.92:50601 LAST_ACK
tcp 0 0 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED
tcp 0 0 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2
tcp 0 0 :::22 :::* LISTEN

格式化输出

[root@chenchen cctmp]# awk '$3==0&& $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s%-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt
01 1 Local-Address Foreign-Address State
07 7 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED
08 8 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED
10 10 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED
14 14 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED

上面一条语句中
$3==0 &&$6=="ESTABLISHED" || NR==1是条件类型(过滤条件)。表示选取$3==0并且 $6=="ESTABLISHED" ,或者NR==1的所有行中进行后面的操作。NR表示行号

printf "%02s %s %-20s %-20s%s\n",NR, FNR, $4,$5,$6是动作,这里使用awk的格式化输出,和C语言的printf没什么两样。

注:其中的“==”为比较运算符。还有其他比较运算符:!=, >, <, >=, <=

 

指定输入字段分隔符

[root@chenchen cctmp]# awk 'BEGIN{FS=":"}$3<10 {print $1,$3,$6}' /etc/passwd
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
sync 5 /sbin
shutdown 6 /sbin
halt 7 /sbin
mail 8 /var/spool/mail
news 9 /etc/news
[root@chenchen cctmp]#

加上BEGIN是因为awk命令在读入第一行的时候,那些变量$1,$2…默认还是以空格键为分割的。因此如果不加BEGIN,仅能在第二行后才开始生效。如下所示:
[root@chenchen cctmp]# awk'{FS=":"} $3<10 {print $1,$3,$6}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
sync 5 /sbin
shutdown 6 /sbin
halt 7 /sbin
mail 8 /var/spool/mail
news 9 /etc/news
[root@chenchen cctmp]#

因此要加上BEGIN关键字。表明awk命令执行前要做的事情。
FS表示以’:’作为输入字段分隔符,打印第一,第三,第六列

条件判断;$3<10:表示第三列的值小于10的才打印出来

上面加BEGIN的命令也等价于:(-F的意思就是指定输入分隔符

[root@chenchen cctmp]# awk -F: ' $3<10{print $1,$3,$6}' /etc/passwd
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
sync 5 /sbin
shutdown 6 /sbin
halt 7 /sbin
mail 8 /var/spool/mail
news 9 /etc/news

注意:-F: 是从第一行开始作用的。
注:如果你要指定多个分隔符,你可以这样来:

awk -F '[;:]'

 

指定输出字段分隔符

        再来看一个以\t作为输出字段分隔符的例子

[root@chenchen cctmp]# awk -F: ' $3<10{print $1,$3,$6}' OFS="\t" /etc/passwd
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
sync 5 /sbin
shutdown 6 /sbin
halt 7 /sbin
mail 8 /var/spool/mail
news 9 /etc/news
[root@chenchen cctmp]#

字符串匹配

[root@chenchen cctmp]# awk '$6 ~ /FIN/ ||NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
1 Local-Address Foreign-AddressState
6 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2
9 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2
13 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1
18 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2
[root@chenchen cctmp]# awk '$6 ~ /WAIT/ ||NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
1      Local-Address   Foreign-AddressState
5      coolshell.cn:80 124.205.5.146:18245    TIME_WAIT
6      coolshell.cn:80 61.140.101.185:37538   FIN_WAIT2
9      coolshell.cn:80 116.234.127.77:11502   FIN_WAIT2
11     coolshell.cn:80 183.60.215.36:36970    TIME_WAIT
13     coolshell.cn:80 124.152.181.209:26825  FIN_WAIT1
15     coolshell.cn:80 183.60.212.163:51082   TIME_WAIT
18     coolshell.cn:80 117.136.20.85:50025    FIN_WAIT2


上面的第一个示例匹配FIN状态,第二个示例匹配WAIT字样的状态。其中
$6表示在第六个字段进行匹配,必须要指明字段。

~ 表示模式开始。

/ /中是模式。这就是一个正则表达式的匹配

例如:指明第三个字段匹配:

[root@chenchen cctmp]# awk '$3 ~/4166/ ||NR==1 {print NR,$0} ' OSF="\t" netstat.txt
1 Proto Recv-Q Send-Q Local-Address Foreign-Address State
12 tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED

其实awk可以像grep一样的去匹配一行,就像这样:
[root@chenchen cctmp]# awk '/LISTEN/'netstat.txt
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 0 :::22 :::* LISTEN

折分文件

        awk拆分文件很简单,使用重定向就好了。下面这个例子,是按第6例分隔文件(第六列相同的分到一个文件),相当的简单(其中的NR!=1表示不处理表头)。

[root@chenchen cctmp]# awk 'NR!=1{print> $6}' netstat.txt

l[root@chenchen cctmp]# ls
ESTABLISHED FIN_WAIT1 FIN_WAIT2 LAST_ACK LISTEN netstat.txt TIME_WAIT

[root@chenchen cctmp]# cat ESTABLISHED
tcp 0 0 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED
tcp 0 0 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED
tcp 0 0 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED
tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED
tcp 0 0 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED
tcp 0 0 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED

[root@chenchen cctmp]# cat FIN_WAIT1
tcp 0 1 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1

[root@chenchen cctmp]# cat FIN_WAIT2
tcp 0 0 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2
tcp 0 0 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2
tcp 0 0 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2

[root@chenchen cctmp]# cat LAST_ACK
tcp 0 1 coolshell.cn:80 208.115.113.92:50601 LAST_ACK

[root@chenchen cctmp]# cat LISTEN
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 0 :::22 :::* LISTEN

[root@chenchen cctmp]# cat TIME_WAIT
tcp 0 0 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT
tcp 0 0 coolshell.cn:80 183.60.215.36:36970 TIME_WAIT
tcp 0 0 coolshell.cn:80 183.60.212.163:51082 TIME_WAIT

awk脚本

        在上面我们可以看到一个END关键字。END的意思是“处理完所有的行的标识”。BEGIN和END这两个关键字意味着执行前和执行后的意思,语法如下:

BEGIN{ 这里面放的是执行前的语句 }

END {这里面放的是处理完所有的行后要执行的语句 }

{这里面放的是处理每一行时要执行的语句}

为了说清楚这个事,我们来看看下面的示例:

假设有这么一个文件(学生成绩表):

[root@chenchen cctmp]# cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62

awk脚本如下
[root@chenchen cctmp]# cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0

printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5,$3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d\n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR,computer/NR
}

我们来看一下执行结果:(也可以这样运行 ./cal.awk score.txt)
[root@chenchen cctmp]# awk -f cal.awkscore.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 63.80 78.60 70.00

上面只是介绍了awk命令的冰山一角,它的功能太强大了,以后继续补充吧。
转自酷客网:AWK 简明教程

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: