awk是Linux/Unix系统中的shell过滤工具,它也是一种自解释的编程语言。
使用awk对某个文件执行一些简单操作,可以直接使用awk '' file 的命令格式操作文件file。
若是进行一些较复杂的理,语句会很长,不易维护。这时,我们可以使用awk脚本来维护。
awk脚本是一个可执行的文件,我们习惯以.awk来命名它。写好的awk脚本,加上可执行权限来使用,格式:./do.awk file
它的内部结构可以简要概括为如下4个部分:
$test.awk
#! /bin/awk -f
BEGIN{}
{}
END{}
第一行告知脚本系统中awk的位置。
第二行是脚本主体之前,执行些什么。该行内的语句,可以只执行一次(这句话的意思,会在后文中举例说明)。
第三行是脚本主体。此中的语句,会根据awk要处理的对象文本中的行数,以及匹配条件,执行零次或多次。
第四行是脚本主体之后,执行些什么。(该部分与BEGIN类似,只是相对于主体的位置不同)。
下面以处理grade.txt文件(来自shell编程教材)为例,说明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 4748 Brown-2 12 30 28
现在,我们想列出学员姓名和目前积分。这个要求实现起来很容易,一条awk语句即可:awk '{print $1,$6}' grade.txt
效果如下:
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
但是这个效果可能对于挑剔的我们来说,不尽人意:列与列对齐的很差,没有列名,等等。
好的,现在我们在原要求基础上,再加三个要求:
1. 要有列名Name和Score;
2. 要在结尾显示这几个学员的总分和平均分;
3. 要求列与列对齐。
咱们先给出最终要求的效果,如下:
Name Score
================
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
The total is 155
The average is 31
这样看起来是不是更美观、合理?这样的实现,虽然也可以一条awk语句搞定,但是那样的语句很长,不利于维护。所以我们使用脚本来维护。
由于是初学,我的第一个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
{
printf"%-10s %5s\n================\n","Name","Score";
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
print "The total is "tot;print "The average is "tot/NR
}
然而增加可执行权限,执行./stu.awk grade.txt 后的效果却是:
Name Score
================
M.Tansley 40
The total is 40
The average is 40
Name Score
================
J.Lulu 24
The total is 64
The average is 32
Name Score
================
P.Bunny 35
The total is 99
The average is 33
Name Score
================
J.Troll 26
The total is 125
The average is 31.25
Name Score
================
L.Tansley 30
The total is 155
The average is 31
这里可见,主体部分的语句,会根据文本匹配行数,执行多次。于是又修改了一下,将Name和Score放到BEGIN中:
我的第二个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
BEGIN{
printf"%-10s %5s\n================\n","Name","Score"
}
{
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
print "The total is "tot;print "The average is "tot/NR
}
执行./stu.awk grade.txt的效果:
Name Score
================
M.Tansley 40
The total is 40
The average is 40
J.Lulu 24
The total is 64
The average is 32
P.Bunny 35
The total is 99
The average is 33
J.Troll 26
The total is 125
The average is 31.25
L.Tansley 30
The total is 155
The average is 31
这次大有改观,Name和Score不会重复出现了。接下来就是总分和平均值重复的问题了。
我的第三个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
BEGIN{
printf"%-10s %5s\n================\n","Name","Score"
}
{
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
}
END{
print "The total is "tot;print "The average is "tot/NR
}
这次,终于出现了预期的结果:
Name Score
================
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
The total is 155
The average is 31
理论上的东西,咱也不多说了,相信通过这三个脚本修改过程,我们应该可以感性的认识到awk脚本中,BEGIN和END的作用了。希望这个例子,可以对初学awk脚本的XDJM们,有所帮助。
愿大家工作愉快!
PS:其实 ./stu.awk grade.txt等同于awk 'BEGIN{...}{...}END{...}' grade.txt(请将对应块中的语句补齐即可,比较长,这也是用awk脚本的原因)这条语句的效果,大家不妨试试看。
使用awk对某个文件执行一些简单操作,可以直接使用awk '' file 的命令格式操作文件file。
若是进行一些较复杂的理,语句会很长,不易维护。这时,我们可以使用awk脚本来维护。
awk脚本是一个可执行的文件,我们习惯以.awk来命名它。写好的awk脚本,加上可执行权限来使用,格式:./do.awk file
它的内部结构可以简要概括为如下4个部分:
$test.awk
#! /bin/awk -f
BEGIN{}
{}
END{}
第一行告知脚本系统中awk的位置。
第二行是脚本主体之前,执行些什么。该行内的语句,可以只执行一次(这句话的意思,会在后文中举例说明)。
第三行是脚本主体。此中的语句,会根据awk要处理的对象文本中的行数,以及匹配条件,执行零次或多次。
第四行是脚本主体之后,执行些什么。(该部分与BEGIN类似,只是相对于主体的位置不同)。
下面以处理grade.txt文件(来自shell编程教材)为例,说明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 4748 Brown-2 12 30 28
现在,我们想列出学员姓名和目前积分。这个要求实现起来很容易,一条awk语句即可:awk '{print $1,$6}' grade.txt
效果如下:
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
但是这个效果可能对于挑剔的我们来说,不尽人意:列与列对齐的很差,没有列名,等等。
好的,现在我们在原要求基础上,再加三个要求:
1. 要有列名Name和Score;
2. 要在结尾显示这几个学员的总分和平均分;
3. 要求列与列对齐。
咱们先给出最终要求的效果,如下:
Name Score
================
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
The total is 155
The average is 31
这样看起来是不是更美观、合理?这样的实现,虽然也可以一条awk语句搞定,但是那样的语句很长,不利于维护。所以我们使用脚本来维护。
由于是初学,我的第一个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
{
printf"%-10s %5s\n================\n","Name","Score";
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
print "The total is "tot;print "The average is "tot/NR
}
然而增加可执行权限,执行./stu.awk grade.txt 后的效果却是:
Name Score
================
M.Tansley 40
The total is 40
The average is 40
Name Score
================
J.Lulu 24
The total is 64
The average is 32
Name Score
================
P.Bunny 35
The total is 99
The average is 33
Name Score
================
J.Troll 26
The total is 125
The average is 31.25
Name Score
================
L.Tansley 30
The total is 155
The average is 31
这里可见,主体部分的语句,会根据文本匹配行数,执行多次。于是又修改了一下,将Name和Score放到BEGIN中:
我的第二个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
BEGIN{
printf"%-10s %5s\n================\n","Name","Score"
}
{
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
print "The total is "tot;print "The average is "tot/NR
}
执行./stu.awk grade.txt的效果:
Name Score
================
M.Tansley 40
The total is 40
The average is 40
J.Lulu 24
The total is 64
The average is 32
P.Bunny 35
The total is 99
The average is 33
J.Troll 26
The total is 125
The average is 31.25
L.Tansley 30
The total is 155
The average is 31
这次大有改观,Name和Score不会重复出现了。接下来就是总分和平均值重复的问题了。
我的第三个awk脚本是这样写的(stu.awk):
#! /bin/awk -f
BEGIN{
printf"%-10s %5s\n================\n","Name","Score"
}
{
(tot+=$6);
printf "%-10s %2d\n",$1,$6;
}
END{
print "The total is "tot;print "The average is "tot/NR
}
这次,终于出现了预期的结果:
Name Score
================
M.Tansley 40
J.Lulu 24
P.Bunny 35
J.Troll 26
L.Tansley 30
The total is 155
The average is 31
理论上的东西,咱也不多说了,相信通过这三个脚本修改过程,我们应该可以感性的认识到awk脚本中,BEGIN和END的作用了。希望这个例子,可以对初学awk脚本的XDJM们,有所帮助。
愿大家工作愉快!
PS:其实 ./stu.awk grade.txt等同于awk 'BEGIN{...}{...}END{...}' grade.txt(请将对应块中的语句补齐即可,比较长,这也是用awk脚本的原因)这条语句的效果,大家不妨试试看。