Linux awk命令简介

来源:互联网 发布:mac dsd播放器 编辑:程序博客网 时间:2024/05/22 05:05

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

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.txtProto Recv-Q  Send-Q  Local-Address          Foreign-Address             Statetcp       0      0  0.0.0.0:3306           0.0.0.0:*                   LISTENtcp       0      0  0.0.0.0:80             0.0.0.0:*                   LISTENtcp       0      0  127.0.0.1:9000         0.0.0.0:*                   LISTENtcp       0      0  coolshell.cn:80        124.205.5.146:18245         TIME_WAITtcp       0      0  coolshell.cn:80        61.140.101.185:37538        FIN_WAIT2tcp       0      0  coolshell.cn:80        110.194.134.189:1032        ESTABLISHEDtcp       0      0  coolshell.cn:80        123.169.124.111:49809       ESTABLISHEDtcp       0      0  coolshell.cn:80        116.234.127.77:11502        FIN_WAIT2tcp       0      0  coolshell.cn:80        123.169.124.111:49829       ESTABLISHEDtcp       0      0  coolshell.cn:80        183.60.215.36:36970         TIME_WAITtcp       0   4166  coolshell.cn:80        61.148.242.38:30901         ESTABLISHEDtcp       0      1  coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1tcp       0      0  coolshell.cn:80        110.194.134.189:4796        ESTABLISHEDtcp       0      0  coolshell.cn:80        183.60.212.163:51082        TIME_WAITtcp       0      1  coolshell.cn:80        208.115.113.92:50601        LAST_ACKtcp       0      0  coolshell.cn:80        123.169.124.111:49840       ESTABLISHEDtcp       0      0  coolshell.cn:80        117.136.20.85:50025         FIN_WAIT2tcp       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      State07 7 coolshell.cn:80      110.194.134.189:1032 ESTABLISHED08 8 coolshell.cn:80      123.169.124.111:49809 ESTABLISHED10 10 coolshell.cn:80      123.169.124.111:49829 ESTABLISHED14 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/passwdroot 0 /rootbin 1 /bindaemon 2 /sbinadm 3 /var/admlp 4 /var/spool/lpdsync 5 /sbinshutdown 6 /sbinhalt 7 /sbinmail 8 /var/spool/mailnews 9 /etc/news[root@chenchen cctmp]#

加上BEGIN是因为awk命令在读入第一行的时候,那些变量$1,$2…默认还是以空格键为分割的。因此如果不加BEGIN,仅能在第二行后才开始生效。如下所示:

[root@chenchen cctmp]# awk'{FS=":"} $3<10 {print $1,$3,$6}' /etc/passwdroot:x:0:0:root:/root:/bin/bash bin 1 /bindaemon 2 /sbinadm 3 /var/admlp 4 /var/spool/lpdsync 5 /sbinshutdown 6 /sbinhalt 7 /sbinmail 8 /var/spool/mailnews 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/passwdroot 0 /rootbin 1 /bindaemon 2 /sbinadm 3 /var/admlp 4 /var/spool/lpdsync 5 /sbinshutdown 6 /sbinhalt 7 /sbinmail 8 /var/spool/mailnews 9 /etc/news

注意:-F: 是从第一行开始作用的。

注:如果你要指定多个分隔符,你可以这样来:

awk -F '[;:]'

 

指定输出字段分隔符

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

[root@chenchen cctmp]# awk -F: ' $3<10{print $1,$3,$6}' OFS="\t" /etc/passwdroot   0       /rootbin    1       /bindaemon 2       /sbinadm    3       /var/admlp     4       /var/spool/lpdsync   5       /sbinshutdown        6      /sbinhalt   7       /sbinmail   8       /var/spool/mailnews   9       /etc/news[root@chenchen cctmp]#

字符串匹配

[root@chenchen cctmp]# awk '$6 ~ /FIN/ ||NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt1      Local-Address   Foreign-AddressState6      coolshell.cn:80 61.140.101.185:37538   FIN_WAIT29      coolshell.cn:80 116.234.127.77:11502   FIN_WAIT213     coolshell.cn:80 124.152.181.209:26825  FIN_WAIT118     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.txt1      Local-Address   Foreign-AddressState5      coolshell.cn:80 124.205.5.146:18245    TIME_WAIT6      coolshell.cn:80 61.140.101.185:37538   FIN_WAIT29      coolshell.cn:80 116.234.127.77:11502   FIN_WAIT211     coolshell.cn:80 183.60.215.36:36970    TIME_WAIT13     coolshell.cn:80 124.152.181.209:26825  FIN_WAIT115     coolshell.cn:80 183.60.212.163:51082   TIME_WAIT18     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.txt1 Proto Recv-Q Send-Q Local-Address          Foreign-Address             State12 tcp        0  4166 coolshell.cn:80       61.148.242.38:30901        ESTABLISHED

其实awk可以像grep一样的去匹配一行,就像这样:

[root@chenchen cctmp]# awk '/LISTEN/'netstat.txttcp       0      0 0.0.0.0:3306           0.0.0.0:*                   LISTENtcp       0      0 0.0.0.0:80             0.0.0.0:*                   LISTENtcp       0      0 127.0.0.1:9000         0.0.0.0:*                   LISTENtcp       0      0 :::22                  :::*                        LISTEN

折分文件

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

[root@chenchen cctmp]# awk 'NR!=1{print> $6}' netstat.txt l[root@chenchen cctmp]# lsESTABLISHED FIN_WAIT1  FIN_WAIT2  LAST_ACK LISTEN  netstat.txt  TIME_WAIT [root@chenchen cctmp]# cat ESTABLISHEDtcp       0      0 coolshell.cn:80        110.194.134.189:1032        ESTABLISHEDtcp       0      0 coolshell.cn:80        123.169.124.111:49809       ESTABLISHEDtcp       0      0 coolshell.cn:80        123.169.124.111:49829       ESTABLISHEDtcp       0   4166 coolshell.cn:80        61.148.242.38:30901         ESTABLISHEDtcp       0      0 coolshell.cn:80        110.194.134.189:4796        ESTABLISHEDtcp       0      0 coolshell.cn:80        123.169.124.111:49840       ESTABLISHED [root@chenchen cctmp]# cat FIN_WAIT1tcp       0      1 coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1 [root@chenchen cctmp]# cat FIN_WAIT2tcp       0      0 coolshell.cn:80        61.140.101.185:37538        FIN_WAIT2tcp       0      0 coolshell.cn:80        116.234.127.77:11502        FIN_WAIT2tcp       0      0 coolshell.cn:80        117.136.20.85:50025         FIN_WAIT2 [root@chenchen cctmp]# cat LAST_ACKtcp       0      1 coolshell.cn:80        208.115.113.92:50601        LAST_ACK [root@chenchen cctmp]# cat LISTENtcp       0      0 0.0.0.0:3306           0.0.0.0:*                   LISTENtcp       0      0 0.0.0.0:80             0.0.0.0:*                   LISTENtcp       0      0 127.0.0.1:9000         0.0.0.0:*                   LISTENtcp       0      0 :::22                  :::*                        LISTEN [root@chenchen cctmp]# cat TIME_WAITtcp       0      0 coolshell.cn:80        124.205.5.146:18245         TIME_WAITtcp       0      0 coolshell.cn:80        183.60.215.36:36970         TIME_WAITtcp       0      0 coolshell.cn:80        183.60.212.163:51082        TIME_WAIT

awk脚本

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

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

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

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

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

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

[root@chenchen cctmp]# cat score.txtMarry  2143 78 84 77Jack   2321 66 78 45Tom    2122 48 77 71Mike   2537 87 97 95Bob    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.txtNAME   NO.   MATH  ENGLISH COMPUTER   TOTAL---------------------------------------------Marry 2143     78       84      77      239Jack  2321     66       78      45      189Tom   2122     48       77      71      196Mike  2537     87       97      95      279Bob   2415     40       57      62      159--------------------------------------------- TOTAL:       319      393     350AVERAGE:    63.80    78.60    70.00

上面只是介绍了awk命令的冰山一角,它的功能太强大了,以后继续补充吧。

转自酷客网:AWK 简明教程。

 

0 0