gawk 命令
gawk程序是Unix中原awk程序的GNU版本。现在我们平常使用的awk其实就是gawk,可以看一下awk命令存放位置,awk建立一个软连接指向gawk,所以在系统中你使用awk或是gawk都一样的。
lrwxrwxrwx 1 root root 4 Mar
27 2010
/bin/awk -> gawk
gawk命令格式
Usage: gawk [POSIX or GNU style
options] -f progfile [--] file ...
Usage: gawk [POSIX or GNU style
options] [--] 'program' file ...
gawk选项
选项
描述
-F fs
指定描绘一行中数据字段的文件分隔符
-f file
指定读取程序的文件名
-v var=value
定义gawk程序中使用的变量和默认值
-mf N
指定数据文件中要处理的字段的最大数目
-mr N
指定数据文件中的最大记录大小
-W keyword
指定gawk的兼容模式或警告级别
gawk的主要功能之一是其处理文本文件中数据的能力。它通过自动将变量分配给每行中的每个数据元素实现这一功能。默认情况下,gawk将下面的变量分配给在文本行中检测到的每个数据字段:
◆
$0表示整行文本
◆
$1表示文本行中的第一个数据字段
◆
$2表示文本行中的第二个数据字段
◆
$n表示文本行中的第n个数据字段
各数据字段依据文本行中的字段分隔符确定。gawk读取一行文本时,使用定义的字段分隔符描述各数据字段。gawk的默认字段分隔符是任意空白字符(如制表符或空格符)
我们来看一个简单的例子:
[root@wh tmp]# cat data1
One line of test text.
Two lines of test text.
Three lines of test text.
[root@wh tmp]# gawk '{print $1}' data1
One
Two
Three
该程序使用$1字段变量仅显示每个文本行中的第一个数据字段。
如果你想读取使用不同字段分隔符的文件,可以使用-F选项:
[root@wh tmp] [root@wh tmp]# gawk -F: '{print $1}'
/etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
。。。
因为/etc/passwd文件中使用冒号分隔数据字段,所以使用
–F:
如果某个文件中使用了分号分隔数据字段,那么使用 –F;
以此类推
[root@wh tmp]# gawk 'BEGIN {print "Hello World!"} {print
$0} END {print "byebye"}'
Hello World!
haha!!!
ç在此输入文本后回车,会在下一行显示内容。
haha!!!
çctrl-D
byebye
BEGIN关键字是在处理任何数据之前应用的命令,即执行该gawk命令行时首先会去执行BEGIN所指定的命令,这里是print “Hello
World!”,接下去{print $0}是我们输入的数据,输入之后回车会立刻显示相应的内容,也就是我们输入的内容,直到按ctrl-D,然后该gawk命令接结束了,但是结束之后还要之END后的结尾命令{print “byebye”}。这样整个过程就结束了。
gawk数据字段和记录变量
变量
描述
FIELDWIDTHS
以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
FS
输入字段分隔符号
RS
输入记录分隔符号
OFS
输出字段分隔符号
ORS
输出记录分隔符号
默认情况下,gawk将OFS变量设置为空格:
[root@wh tmp]# cat data1
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,data32,data33,data34,data35
[root@wh tmp]# gawk 'BEGIN{FS=","} {print $1,$2,$3}'
data1
data11 data12 data13
data21 data22 data23
data31 data32 data33
通过设置OFS变量,可以使用任何字符串分隔符输出中的数据字段:
[root@wh tmp]# gawk 'BEGIN{FS=",";OFS="-"} {print
$1,$2,$3}' data1
data11-data12-data13
data21-data22-data23
data31-data32-data33
[root@wh tmp]# gawk 'BEGIN{FS=",";OFS="--"} {print
$1,$2,$3}' data1
data11--data12--data13
data21--data22--data23
data31--data32--data33
[root@wh tmp]# gawk
'BEGIN{FS=",";OFS=""} {print
$1,$2,$3}' data1
data11data12data13
data21data22data23
data31data32data33
更多gawk内置变量
变量
描述
ARGC
出现的命令行参数的个数
ARGIND
当前正在处理的文件在ARGV中的索引
ARGV
命令行参数数组
CONVFMT
数字的转换格式(参见printf语句)。默认值为%.6g
ENVIRON
当前shell环境变量及其值的关联数组
ERRNO
当读取或关闭输入文件时发生错误时的系统错误
FILENAME
用于输入到gawk程序的数据文件的文件名
FNR
数据文件的当前记录号
IGNORECASE
如果设置为非0,则忽略gawk命令中使用的字符串的大小写
NF
数据文件中数据字段的个数
NR
已处理的输入记录的个数
OFMT
显示数字的输出格式。默认为%,6g
RLENGTH
匹配函数中匹配上的子字符串的长度
RSTART
匹配函数中匹配上的子字符串的开始索引
[root@wh tmp]# gawk 'BEGIN {print ARGC,ARGV[1]}'
data1
2 data1
ARGC变量表示命令行上有两个参数。这包括gawk命令和data1参数(注意,程序脚本不是参数)。ARGV数组以索引0开始,它表示命令。第一个数组值是gawk命令后的第一个命令行参数。与shell变量不同的是在脚本中引用gawk变量时,不需要再变量名称前加美元符号。
FNR、NF和NR变量在gawk程序中用于跟踪数据字段和记录。有时,你可能不知道记录中具体有多少个数据字段。NF变量允许指出记录中的最后一个数据字段而不需要知道它的位置:
[root@wh tmp]# gawk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}'
/etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
NF变量包含数据文件中最后一个数据字段的数值。通过在前面加美元符号,可以将其作为数据字段变量使用。
FNR和NR变量相类似,只是略有不同。FNR变量包含当前数据文件中处理的记录数。NR变量包含已经处理的记录的总数。让我们看几个例子来了解它们的不同之处:
[root@wh tmp]# gawk 'BEGIN{FS=",";} {print $1,"FNR="FNR}'
data1 data1
data11 FNR=1
data21 FNR=2
data31 FNR=3
data11 FNR=1
data21 FNR=2
data31 FNR=3
本例中,gawk程序命令行定义了两个输入文件(它两次都指定了同一输入文件)。脚本打印第一个数据字段的值和FNR变量的当前值。请注意,FNR变量在gawk程序处理第二个数据文件时被重新设置为1。
现在,让我们添加NR变量,看看结果是什么:
[root@wh tmp]# gawk 'BEGIN{FS=",";} {print
$1,"FNR="FNR,"NR="NR} END {print "There were",NR,"records
processed"}' data1 data1
data11 FNR=1 NR=1
data21 FNR=2 NR=2
data31 FNR=3 NR=3
data11 FNR=1 NR=4
data21 FNR=2 NR=5
data31 FNR=3 NR=6
There were 6 records processed
FNR变量值在gawk处理第二个数据文件时被重置,但NR变量在处理第二个数据文件时仍然继续增加。也就是说,如果只使用一个
文件作为输入,则FNR和NR值将是相同的。如果使用多个数据文件作为输入,则FNR值在每次处理新的数据文件时重置,而NR值对所有数据文件进行累计计数。
使用正则表达式和匹配操作符
[root@wh tmp]# gawk 'BEGIN{FS=","} /11/{print $1}'
data1
data11
[root@wh tmp]# gawk 'BEGIN{FS=","} /d/{print $1}'
data1
data11
data21
data31
[root@wh tmp]# gawk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}'
data1
data21,data22,data23,data24,data25
匹配操作符将第二个数据字段与正则表达式/^data2/进行比较,/^data2/表示以文本data2开头的字符串。
这是一种在gawk程序脚本中常用的,也是非常好用的方法,用于在数据文件中搜索特定的数据元素:
[root@wh tmp]# awk -F: '$1 ~ /root/ {print $1,$NF}'
/etc/passwd
root /bin/bash
此示例在第一个数据字段中搜索文本root,当在记录中找到模式时,打印出记录的第一个和最后一个数据字段。
还可以通过!符号否定正则表达式的匹配:
$1 !~ /expression/
如果没有在记录中找到正则表达式,则程序脚本将应用到记录数据上:
[root@wh tmp]# gawk 'BEGIN{FS=","} $2 !~ /^data2/ {print
$1}' data1
data11
data31
在本例中,gawk程序脚本打印记录的第二个数据字段不以data2开头的第一个数据字段。
除了正则表达式,还可以在匹配模式中使用数学 。当数据字段中包含数值时,使用这一功能将非常得心应手。例如,想显示所有属于根用户组(组号为0)的系统用户:
[root@wh tmp]# gawk -F: '$4 == 0 {print $1}'
/etc/passwd
root
sync
shutdown
halt
operator
可以使用常规的数学比较表达式:
◆
X == y
◆
X <= y
◆
X < y
◆
X > y
◆
X >= y
[root@wh tmp]# gawk -F, '$1 == "data" {print $1}'
data1
[root@wh tmp]# gawk -F, '$1 == "data11" {print $1}'
data1
data11
第一个测试不匹配任何记录,因为第一个数据字段值data不存在于任何记录。第二个测试匹配值为data11的一条记录。
接下去我们来一些实际使用的例子:
1)查看TCP连接状态
[root@Log-Storage-1 ~]# netstat
-n |awk '$1 ~ /^tcp/ {++S[$NF]} END {for(a in S) print a,
S[a]}'
CLOSE_WAIT 5
ESTABLISHED 20
TIME_WAIT 61
2)对于apache日志中指定某个页面进行手动pv或是uv的查询
[root@wh tmp]# cat
ga.sdo.com_12.01.28.all |gawk '$7 ~ //wh/index/index.asp/
{++S[$7]} END {for(a in S) print a,S[a]}'
http://ga.sdo.com/wh/index/index.asp" 889
http://ga.sdo.com/wh/index/index.asp?" 2
第二行不是我们所需要的,所以我们要修改一下:
[root@wh tmp]# cat
ga.sdo.com_12.01.28.all |gawk '$7 ~ //wh/index/index.asp"/
{++S[$7]} END {for(a in S) print a,S[a]}'
http://ga.sdo.com/wh/index/index.asp" 889
现在这个就是我们要的结果了,PV为889。
接下来我们查uv
[root@wh tmp]# cat ga.sdo.com_12.01.28.all |gawk '$7 ~
//wh/index/index.asp"/ {print $1}'|sort|uniq|wc -l
744
我们查到744,这个就是我们需要的UV了。
求和
[root@wh tmp]# cat ga.sdo.com_12.01.28.all |gawk
'$7 ~ /htm/ {++S[$7]} END {for(a in S) print a,S[a]}'|gawk
'{sum+=$2} END {print sum}'
4571
对包含htm的URL进行分类统计,然后对统计结果的求和。