awk用法总结



awk:好用的数据处理工具

 

awk 也是一个非常棒的数据处理工具!sed 常常用于一整个行的处理, awk 则比较倾向于一行当中分成数个『栏位』(或者称为一个域,也就是一列)来处理。因此,awk 相当的适合处理小型的数据数据处理呢!awk 通常运行的模式是这样的:

[root@www ~]# awk '条件类型1{动作1} 条件类型2{动作2} ...' filename


awk 后面接两个单引号并加上大括号 {} 来配置想要对数据进行的处理动作。 awk 可以处理后续接的文件,也可以读取来自前个命令的 standard output 。 但如前面说的, awk 主要是处理『每一行的栏位内的数据』,而默认的『栏位的分隔符号为 "空白键" 或 "[tab]键" 』!举例来说,我们用 last 可以将登陆者的数据取出来,结果如下所示:

 

[root@www ~]# last -n 5 <==仅取出前五行
root     pts/1   192.168.1.100  Tue Feb 10 11:21   still logged in
root     pts/1   192.168.1.100  Tue Feb 10 00:46 - 02:28  (01:41)
root     pts/1   192.168.1.100  Mon Feb  9 11:41 - 18:30  (06:48)
dmtsai   pts/1   192.168.1.100  Mon Feb  9 11:41 - 11:41  (00:00)
root     tty1                   Fri Sep  5 14:09 - 14:10  (00:01)

 

若我想要取出帐号与登陆者的 IP ,且帐号与 IP 之间以 [tab] 隔开,则会变成这样:

[root@www ~]# last -n 5 | awk '{print $1 "\t" $3}'
root    192.168.1.100
root    192.168.1.100
root    192.168.1.100
dmtsai  192.168.1.100
root    Fri


上表是 awk 最常使用的动作!透过 print 的功能将栏位数据列出来!栏位的分隔则以空白键或 [tab] 按键来隔开。 因为不论哪一行我都要处理,因此,就不需要有 "条件类型" 的限制!我所想要的是第一栏以及第三栏, 但是,第五行的内容怪怪的~这是因为数据格式的问题啊!所以罗~使用 awk 的时候,请先确认一下你的数据当中,如果是连续性的数据,请不要有空格或 [tab] 在内,否则,就会像这个例子这样,会发生误判喔!

另外,由上面这个例子你也会知道,在每一行的每个栏位都是有变量名称的,那就是 $1, $2... 等变量名称。以上面的例子来说, root 是 $1 ,因为他是第一栏嘛!至於 192.168.1.100 是第三栏, 所以他就是 $3 啦!后面以此类推~呵呵!还有个变量喔!那就是 $0 ,$0 代表『一整列数据』的意思~以上面的例子来说,第一行的 $0 代表的就是『root .... 』那一行啊! 由此可知,刚刚上面五行当中,整个 awk 的处理流程是:

  1. 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中;
  2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";
  3. 做完所有的动作与条件类型;
  4. 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。

经过这样的步骤,你会晓得, awk 是『以行为一次处理的单位』, 而『以栏位为最小的处理单位』。好了,那么 awk 怎么知道我到底这个数据有几行?有几栏呢?这就需要 awk 的内建变量的帮忙啦~

变量名称代表意义
NF每一行 ($0) 拥有的栏位总数
NR目前 awk 所处理的是『第几行』数据
FS目前的分隔字节,默认是空白键

我们继续以上面 last -n 5 的例子来做说明,如果我想要:

  • 列出每一行的帐号(就是 $1);
  • 列出目前处理的行数(就是 awk 内的 NR 变量)
  • 并且说明,该行有多少栏位(就是 awk 内的 NF 变量)

则可以这样:

Tips:
要注意喔,awk 后续的所有动作是以单引号『 ' 』括住的,由於单引号与双引号都必须是成对的, 所以, awk 的格式内容如果想要以 print 列印时,记得非变量的文字部分,包含上一小节 printf 提到的格式中,都需要使用双引号来定义出来喔!因为单引号已经是 awk 的命令固定用法了!
鸟哥的图示

[root@www ~]# last -n 5| awk '{print $1 "\t lines: " NR "\t columns: " NF}'
root     lines: 1        columns: 10
root     lines: 2        columns: 10
root     lines: 3        columns: 10
dmtsai   lines: 4        columns: 10
root     lines: 5        columns: 9
# 注意喔,在 awk 内的 NR, NF 等变量要用大写,且不需要有钱字号 $ 啦!
 
这样可以了解 NR 与 NF 的差别了吧?好了,底下来谈一谈所谓的 "条件类型" 了吧!
 
 
:$0 表示整行,$1 代表第一项

 

  • awk 的逻辑运算字节

既然有需要用到 "条件" 的类别,自然就需要一些逻辑运算罗~例如底下这些:

运算单元代表意义
>大於
<小於
>=大於或等於
<=小於或等於
==等於
!=不等於

值得注意的是那个『 == 』的符号,因为:

  • 逻辑运算上面亦即所谓的大於、小於、等於等判断式上面,习惯上是以『 == 』来表示;
  • 如果是直接给予一个值,例如变量配置时,就直接使用 = 而已。

好了,我们实际来运用一下逻辑判断吧!举例来说,在 /etc/passwd 当中是以冒号 ":" 来作为栏位的分隔, 该文件中第一栏位为帐号,第三栏位则是 UID。那假设我要查阅,第三栏小於 10 以下的数据,并且仅列出帐号与第三栏, 那么可以这样做:

[root@www ~]# cat /etc/passwd | \
> awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
root:x:0:0:root:/root:/bin/bash
bin      1
daemon   2
....(以下省略)....


有趣吧!不过,怎么第一行没有正确的显示出来呢?这是因为我们读入第一行的时候,那些变量 $1, $2... 默认还是以空白键为分隔的,所以虽然我们定义了 FS=":" 了, 但是却仅能在第二行后才开始生效。那么怎么办呢?我们可以预先配置 awk 的变量啊! 利用 BEGIN 这个关键字喔!这样做:

[root@www ~]# cat /etc/passwd | \
> awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
root     0
bin      1
daemon   2
......(以下省略)......


很有趣吧!而除了 BEGIN 之外,我们还有 END 呢!另外,如果要用 awk 来进行『计算功能』呢?以底下的例子来看, 假设我有一个薪资数据表档名为 pay.txt ,内容是这样的:

Name    1st     2nd     3th
VBird   23000   24000   25000
DMTsai  21000   20000   23000
Bird2   43000   42000   41000


如何帮我计算每个人的总额呢?而且我还想要格式化输出喔!我们可以这样考虑:

  • 第一行只是说明,所以第一行不要进行加总 (NR==1 时处理);
  • 第二行以后就会有加总的情况出现 (NR>=2 以后处理)
[root@www ~]# cat pay.txt | \
> awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }
NR>=2{total = $2 + $3 + $4
printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
      Name        1st        2nd        3th      Total
     VBird      23000      24000      25000   72000.00
    DMTsai      21000      20000      23000   64000.00
     Bird2      43000      42000      41000  126000.00


上面的例子有几个重要事项应该要先说明的:

  • awk 的命令间隔:所有 awk 的动作,亦即在 {} 内的动作,如果有需要多个命令辅助时,可利用分号『;』间隔, 或者直接以 [Enter] 按键来隔开每个命令,例如上面的范例中,鸟哥共按了三次 [enter] 喔!
  • 逻辑运算当中,如果是『等於』的情况,则务必使用两个等号『==』!
  • 格式化输出时,在 printf 的格式配置当中,务必加上 \n ,才能进行分行!
  • 与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。

利用 awk 这个玩意儿,就可以帮我们处理很多日常工作了呢!真是好用的很~ 此外, awk 的输出格式当中,常常会以 printf 来辅助,所以, 最好你对 printf 也稍微熟悉一下比较好啦!另外, awk 的动作内 {} 也是支持 if (条件) 的喔! 举例来说,上面的命令可以修订成为这样:

[root@www ~]# cat pay.txt | \
> awk '{if(NR==1) printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}
NR>=2{total = $2 + $3 + $4
printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'


你可以仔细的比对一下上面两个输入有啥不同~从中去了解两种语法吧!我个人是比较倾向於使用第一种语法, 因为会比较有统一性啊! ^_^




awk 实例练习(一)

前一篇学习了awk的基本知识,现在来做一些练习加深一下印象。

假设我们有这样一个待处理的文件"grade.txt":

M.Tansley     05/99     48311     Green     8     40     44
J.Lulu     06/99     48317     green     9     24     26
P.Bunny     02/99     48     Yellow     12     35     28
J.Troll     07/99     4842     Brown-3     12     26     26
L.Tansley     05/99     4712     Brown-2     12     30     28
 
#打印整个文件
zhuyupeng@zhuyupeng-PC ~
$ awk '{print $0}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu          06/99   48317   green   9       24      26
P.Bunny         02/99   48      Yellow  12      35      28
J.Troll         07/99   4842    Brown-3 12      26      26
L.Tansley       05/99   4712    Brown-2 12      30      28

#打印第一和第四个域
zhuyupeng@zhuyupeng-PC ~
$ awk '{print $1,$4}' grade.txt
M.Tansley Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley Brown-2

 
#打印表头
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {print "Name            Belt\n---------------------------"}
> {print $1"\t"$4}' grade.txt
Name            Belt
---------------------------
M.Tansley       Green
J.Lulu  green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley       Brown-2

正则表达式相关
 
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用 i f语句。awk中if后面的条件用()括起来。
#下面代码打印$4 包含 Brown 的行
zhuyupeng@zhuyupeng-PC ~
$ awk '$4~/Brown/ {print $0}' grade.txt
J.Troll         07/99   4842    Brown-3 12      26      26
L.Tansley       05/99   4712    Brown-2 12      30      28
 
#非精确匹配
zhuyupeng@zhuyupeng-PC ~
$ awk '$3 ~/48/ {print $0}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu          06/99   48317   green   9       24      26
P.Bunny         02/99   48      Yellow  12      35      28
J.Troll         07/99   4842    Brown-3 12      26      26
 
#精确匹配
zhuyupeng@zhuyupeng-PC ~
$ awk '$3=="48" {print $0}' grade.txt
P.Bunny         02/99   48      Yellow  12      35      28
 
 
 
#不匹配 使用 ‘!~’
zhuyupeng@zhuyupeng-PC ~
$ awk '$0 !~ /Brown/' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu          06/99   48317   green   9       24      26
P.Bunny         02/99   48      Yellow  12      35      28
 
zhuyupeng@zhuyupeng-PC ~
$ awk '$4 != "Brown-2" {print $0}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu          06/99   48317   green   9       24      26
P.Bunny         02/99   48      Yellow  12      35      28
J.Troll         07/99   4842    Brown-3 12      26      26
 
#小于
zhuyupeng@zhuyupeng-PC ~
$ awk '$6 < $7 {print $0 "$1 Try better at the next comp"}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44$1 Try better at the next comp
J.Lulu          06/99   48317   green   9       24      26$1 Try better at the next comp
 
#设置大小写
zhuyupeng@zhuyupeng-PC ~
$ awk '/[Gg]reen/' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu          06/99   48317   green   9       24      26
 
#匹配第一个域的第三个字符是‘a’
zhuyupeng@zhuyupeng-PC ~
$ awk '$1 ~/^...a/' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
L.Tansley       05/99   4712    Brown-2 12      30      28
 
#'或'匹配,使用 ‘|’ ,需使用括号括起来
zhuyupeng@zhuyupeng-PC ~
$ awk '$0 ~/(Yellow|Brown)/' grade.txt
P.Bunny         02/99   48      Yellow  12      35      28
J.Troll         07/99   4842    Brown-3 12      26      26
L.Tansley       05/99   4712    Brown-2 12      30      28


awk 实例练习(二)

上一篇,这里使用的grade.txt 也是和上一篇中的相同。

先来总结一下awk内置变量:

ARGC          命令行参数个数
ARGV          命令行参数排列
ENVIRON       支持队列中系统环境变量的使用
FILENAME      awk浏览文件名
FNR           浏览文件的记录数
FS            设置输入域分隔符,等价于命令行-F选项
NF            浏览记录的域个数
NR            已读的记录数
OFS           输出域分隔符
ORS           输出例句分隔符
RS            控制记录分隔符
 
 
zhuyupeng@zhuyupeng-PC ~
$ awk '{print NF,NR,$0} END {print FILENAME}' grade.txt
7 1 M.Tansley   05/99   48311   Green   8       40      44
7 2 J.Lulu      06/99   48317   green   9       24      26
7 3 P.Bunny     02/99   48      Yellow  12      35      28
7 4 J.Troll     07/99   4842    Brown-3 12      26      26
7 5 L.Tansley   05/99   4712    Brown-2 12      30      28
grade.txt
 
#使用 -F 参数指定分隔符
zhuyupeng@zhuyupeng-PC ~
$ echo $PWD
/home/zhuyupeng
 
zhuyupeng@zhuyupeng-PC ~
$ echo $PWD | awk -F/ '{print $NF"\t"NF}'
zhuyupeng       3

#设置变量名,将27 赋值给变量BASELINE
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {BASELINE="27"} $6<BASELINE {print $0}' grade.txt
J.Lulu  06/99   48317   green   9       24      26
J.Troll 07/99   4842    Brown-3 12      26      26

#修改数值域取值,注意‘{}’
zhuyupeng@zhuyupeng-PC ~
$ awk '{if($1=="M.Tansley") $6=$6-1; print $1,$6,$7}' grade.txt
M.Tansley 39 44
J.Lulu 24 26
P.Bunny 35 28
J.Troll 26 26
L.Tansley 30 28
 
#修改文本域取值
zhuyupeng@zhuyupeng-PC ~
$ awk '{if($1=="J.Troll") $1="J.L.Troll"; print $1}' grade.txt
M.Tansley
J.Lulu
P.Bunny
J.L.Troll
L.Tansley

#创建新的输出域,这里新的输出域为 diff
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {print "Name \t Difference"} {if($6<$7) {diff=$7-$6; print $1,diff}}' grade.txt
Name     Difference
M.Tansley 4
J.Lulu 2
 
#统计某一个域的和,使用‘+=’ 下面的例子统计第六个域的和
zhuyupeng@zhuyupeng-PC ~
$ awk '(tot+=$6); END{print "Club student total points: " tot}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu  06/99   48317   green   9       24      26
P.Bunny 02/99   48      Yellow  12      35      28
J.Troll 07/99   4842    Brown-3 12      26      26
L.Tansley       05/99   4712    Brown-2 12      30      28
Club student total points: 155

#注意区别,加‘{}’则不打印文件
zhuyupeng@zhuyupeng-PC ~
$ awk '{(tot+=$6)}; END{print "Club student total points: " tot}' grade.txt
Club student total points: 155

awk 内置字符串函数
 
gsub(r,s)          在整个$0中用s替代r
gsub(r,s,t)        在整个t中使用s替代r
index(s,t)         在返回s中字符串t的第一个位置
length(s)          放回s长度
match(s,r)         测试s是否包含匹配r的字符串
split(s,a,fs)      在fs上将s分成序列a
sprint(fmt,exp)    返回经fmt格式化后的exp
sub(r,s)           用$0中最左边最长的子串代替s
substr(s,p)        返回字符串s中从p开始的后缀部分
substr(s,p,n)      返回字符串s中从p开始长度为n的后缀部分
 
#替换,目标串使用正则表达式格式‘//’
zhuyupeng@zhuyupeng-PC ~
$ awk 'gsub(/4842/,4899) {print $0}' grade.txt
J.Troll 07/99   4899    Brown-3 12      26      26
 
#查询字符串第一次出现的位置,注意使用BEGIN,否则每一行都会打印,字符串使用引号括起来
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN{print index("Bunny","ny")}' grade.txt
4
 
#长度
zhuyupeng@zhuyupeng-PC ~
$ awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll

#match 使用: 找不到返回0,找到返模式串在匹配串中的位置
#注:单独使用 加BEGIN
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {print match("ANCD",/d/)}'
0

#以下两种模式都正确
zhuyupeng@zhuyupeng-PC ~
$ awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
 
zhuyupeng@zhuyupeng-PC ~
$ awk '$1=="J.Lulu" {print match($1,/u/)}' grade.txt
4

#split 返回字符串数组元素个数
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {print split("123#456#789",myarray,"#");print myarray[1],myarray[2],myarray[3]}'
3
123 456 789

#sub,发现并替换模式的第一个位置
zhuyupeng@zhuyupeng-PC ~
$ awk '$1=="J.Troll" {sub(26,29,$0)} {print $0}' grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu  06/99   48317   green   9       24      26
P.Bunny 02/99   48      Yellow  12      35      28
J.Troll 07/99   4842    Brown-3 12      29      26
L.Tansley       05/99   4712    Brown-2 12      30      28
 
#substr,返回字符串指定范围内的子串
zhuyupeng@zhuyupeng-PC ~
$ awk '$1=="L.Tansley" {print substr($1,1,5)}' grade.txt
L.Tan

#使用substr返回指定位置开始的后缀部分,范围只给了一个参数,注意和上一个例子相对比
zhuyupeng@zhuyupeng-PC ~
$ awk '{print substr($1,3)}' grade.txt
Tansley
Lulu
Bunny
Troll
Tansley

#从shell中向awk传递字符串,通过 echo 加管道的方式
zhuyupeng@zhuyupeng-PC ~
$ echo "Test" | awk '{print length($0)}'
4
 
zhuyupeng@zhuyupeng-PC ~
$ STR="mydoc.txt"
 
zhuyupeng@zhuyupeng-PC ~
$ echo $STR | awk '{print substr($STR,7)}'
txt


awk 实例练习 (三)

awk 使用printf 
 
#printf使用类似于C语言
#字符转换
zhuyupeng@zhuyupeng-PC ~
$ echo "65" | awk '{printf "%c\n",$0}'
A
 
zhuyupeng@zhuyupeng-PC ~
$ echo "99" | awk '{printf "%f\n",$0}'
99.000000
 
#格式化输出
#打印名字,左对齐,使用‘-’
zhuyupeng@zhuyupeng-PC ~
$ awk '{printf "%-15s %s\n",$1,$3}' grade.txt
M.Tansley       48311
J.Lulu          48317
P.Bunny         48
J.Troll         4842
L.Tansley       4712
 
#向awk传入参数
zhuyupeng@zhuyupeng-PC ~
$ awk '{if ($5 < AGE) print $0}' AGE=10 grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu  06/99   48317   green   9       24      26
 
zhuyupeng@zhuyupeng-PC ~
$ df -k
文件系统                1K-块     已用    可用 已用% 挂载点
D:/Program Files/bin 76155900 70397660 5758240   93% /usr/bin
D:/Program Files/lib 76155900 70397660 5758240   93% /usr/lib
D:/Program Files     76155900 70397660 5758240   93% /
C:                   40857596 32552996 8304600   80% /cygdrive/c
D:                   76155900 70397660 5758240   93% /cygdrive/d
 
zhuyupeng@zhuyupeng-PC ~
$ df -k | awk '($4 ~/^[0-9]/) {if($4 > TRIGGER) print $6"\t"$4}' TRIGGER=80000
93%     70397660
93%     70397660
93%     70397660
/cygdrive/c     8304600
/cygdrive/d     5758240
  
 
#awk脚本
下面的脚本是将该命令翻译成为一个完整脚本的形式: awk '(tot+=$6); END{print "Club student total points: " tot}' grade.txt
 
#!/bin/awk -f
#print a header first
BEGIN{
    print "Student  Date    Member No.   Grade   Age   Points   Max"
    print "Name     Joined                             Gained   Point Available"
    print "==================================================================="
}
#let's add the scores of points gained
(tot+=$6)
#finished processing
END{
    print "Club student total points :" tot
    print "Average Club Student points:" tot/NR
    } 
 
#脚本运行是通过secureCRT 登陆远程的服务器运行的,控制台略有不同
 
[chen@localhost zyp]$ ./stu_tot.awk  grade.txt                                            
Student  Date    Member No.   Grade   Age   Points   Max
Name     Joined                             Gained   Point Available
===================================================================
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu  06/99   48317   green   9       24      26
P.Bunny 02/99   48      Yellow  12      35      28
J.Troll 07/99   4842    Brown-3 12      26      26
L.Tansley       05/99   4712    Brown-2 12      30      28
Club student total points :155
Average Club Student points:31
 
 
#一个文件中如果有相同的行连续出现就只打印一次
 
strip.awk:
 
#!/bin/awk -f
#error_strip.awk
#to call: error_strip.awk <filename>
#strips out the ERROR* lines if there are more than one
#ERROR* lines after each filed record.
BEGIN{
    error_line=""
}
    #tell awk the whole is "ERROR *"
    {
        if ($0 == "ERROR*" && error_line == "ERROR*")
            next;
        error_line = $0;
        print
    }

 
stip.txt:
INVALID LCSD 98GJ23
ERROR*
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*
ERROR*
ERROR*
ERROR*
ERROR*
PASS FILED INVALID ON GHSI
ERROR*
CUTION LPSS ERROR ON ACC NO.
ERROR*
ERROR*
 
[chen@localhost zyp]$ ./strip.awk strip.txt
INVALID LCSD 98GJ23
ERROR*
CAUTION LPSS ERROR ON ACC NO.
ERROR*
PASS FILED INVALID ON GHSI
ERROR*
CUTION LPSS ERROR ON ACC NO.
ERROR*
 
#在awk中使用FS变量指定分隔符的时候,FS一定要放在BEGIN部分
 
#!/bin/awk -f
#to call :passwd.awk /etc/passwd
#print out the first and fifth fields
BEGIN{
    FS=":"
}
{ print $1,"\t",$5} #第一域是帐号名,第五域是账号所有者


 
[chen@localhost zyp]$ ./passwd.awk /etc/passwd
root     root
bin      bin
daemon   daemon
adm      adm
lp       lp
sync     sync
shutdown         shutdown
halt     halt
mail     mail
uucp     uucp
operator         operator
games    games
gopher   gopher
ftp      FTP User
nobody   Nobody
...
 
#向AWK脚本传递参数
 
age.awk:
 
#!/bin/awk -f
#name: age.awk
#to call : age.awk AGE=n grade.txt
#prints ages that are lower than the age supplied on the command line
{
    if ( $5 < AGE )
        print $0
}

 
grade.txt:(前面已经给出)
 
[chen@localhost zyp]$ ./age.awk AGE=10 grade.txt
M.Tansley       05/99   48311   Green   8       40      44
J.Lulu  06/99   48317   green   9       24      26
 
 
#awk 数组,awk数组是类似于一个键值对,既可以使用数字做下标,也可以使用字符串做下标
 
前面介绍过split函数,并使用了一个例子:
$awk 'BEGIN {print split("123#456#789",myarray,"#")}'
3
上面例子中,split返回数组myarray下标数,实际上myarray数组为:
myarray[1]="123"
myarray[2]="456"
myarray[3]="789"
 
数组使用前不必定义,也不必指定数组元素个数。经常使用循环来方位数组,一般这样使用循环:
for(element in array ) print array[element]
 
#下面脚本先将 "123#456#789" 使用split环峰,再循环打印个数组元素
 
#!/bin/awk -f
#name: arraytest.awk
#prints out an array
BEGIN{
    record="123#456#789";
    split(record,myarray,"#")
}

END{
    for ( i in myarray )
       {
           print myarray[i]
       }
}


#要运行脚本 需要使用/dev/null作为输入文件
[chen@localhost zyp]$ ./arraytest.awk  /dev/null
123
456
789
 
 
grade_student.txt:
 
Yellow#Junior
Orange#Senior
Yellow#Junior
Purple#Junior
Brown-2#Junior
White#Senior
Orange#Senior
Red#Junior
Brown-2#Senior
Yellow#Senior
Red#Junior
Blue#Senior
Green#Senior
Purple#Junior
White#Junior
 
 
belts.awk:
 
#!/bin/awk -f
#name: belts.awk
#to call: belts.awk grade2.txt
#loops through the grade2.txt file and counts how many
#belts we have in(yellow,orange,red)
#also count how many adults and juniors we have
#
#start of BEGIN
#set FS and load the arrays and our values
BEGIN{
    FS="#"
    #load the belt colours we are interested in only
    belt["Yellow"]
    belt["Orange"]
    belt["Red"]
    #end of BEGIN
    #load the student type
    student["Junior"]
    student["Senior"]
}
#loop thru array that holds the belt colours against field-1
#if we have a match,keep a running total
{ for (colour in belt)
    {
        if ($1==colour)
            belt[colour]++
    }
}
    #loop thru array that holds the student type against
    #field-2 if we have a match, keep a running total
       { for(senior_or_junior in student)
           {
               if($2 == senior_or_junior)
                   student[senior_or_junior]++
           }
       }
    #finished processing so print out the matches..for each array
END{ for(colour in belt)
       print "The club has",belt[colour],colour,"Belts"

        for(senior_or_junior in student)
             print "The club has",student[senior_or_junior]\
                            , senior_or_junior, "students"
   }



##
 
##
脚本的作用:
1.统计Yellow、Orange和Red级别的人各是多少
2.俱乐部中有多少成年(Senior)和未成年人(Junior)

 
 
 
#
[chen@localhost ~]$ ./belts.awk grade_student.txt
The club has 2 Red Belts
The club has 2 Orange Belts
The club has 3 Yellow Belts
The club has 7 Senior students
The club has 8 Junior students





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值