Chinaunix首页 | 论坛 | 博客
  • 博客访问: 138159
  • 博文数量: 37
  • 博客积分: 2671
  • 博客等级: 少校
  • 技术积分: 335
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-11 13:18
文章分类

全部博文(37)

文章存档

2011年(16)

2010年(21)

我的朋友

分类:

2011-01-26 20:06:26

awk的流程控制

流程控制语句是任何程序设计语言都不能缺少的部分。任何好的语言都有一些执行流程控制的语句。awk提供的完备的流程控制语句类似于C语言,这给我们编程带来了极大的方便。

1、BEGIN和END:

在 awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初 始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫 描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。

例:累计销售文件xs中的销售金额(假设销售金额在记录的第三字段):

$awk
>'BEGIN { FS=":";print "统计销售金额";total=0}
>{print $3;total=total+$3;}
>END {printf "销售金额总计:%.2f",total}' sx
(注:>是shell提供的第二提示符,如要在shell程序awk语句和awk语言中换行,则需在行尾加反斜杠\)

在这里,BEGIN预置了内部变量FS(字段分隔符)和自定义变量total,同时在扫描之前显示出输出行头。而END则在扫描完成后打印出总合计。

2、流程控制语句
awk提供了完备的流程控制语句,其用法与C语言类似。下面我们一一加以说明:

2.1、if...else语句:

格式:
if(表达式)
语句1
else
语句2

格式中"语句1"可以是多个语句,如果你为了方便awk判断也方便你自已阅读,你最好将多个语句用{}括起来。awk分枝结构允许嵌套,其格式为:

if(表达式1)
{if(表达式2)
语句1
else
语句2
}
语句3
else {if(表达式3)
语句4
else
语句5
}
语句6

当然实际操作过程中你可能不会用到如此复杂的分枝结构,这里只是为了给出其样式罢了。

2.2、while语句

格式为:

while(表达式)
语句

2.3、do-while语句

格式为:

do
{
语句
}while(条件判断语句)

2.4、for语句

格式为:

for(初始表达式;终止条件;步长表达式)
{语句}

在 awk的 while、do-while和for语句中允许使用break,continue语句来控制流程走向,也允许使用exit这样的语句来退出。 break中断当前正在执行的循环并跳到循环外执行下一条语句。continue从当前位置跳到循环开始处执行。对于exit的执行有两种情况:当 exit语句不在END中时,任何操作中的exit命令表现得如同到了文件尾,所有模式或操作执行将停止,END模式中的操作被执行。而出现在END中的 exit将导致程序终止。


awk中的自定义函数

定义和调用用户自己的函数是几乎每个高级语言都具有的功能,awk也不例外,但原始的awk并不提供函数功能,只有在nawk或较新的awk版本中才可以增加函数。

函数的使用包含两部分:函数的定义与函数调用。其中函数定义又包括要执行的代码(函数本身)和从主程序代码传递到该函数的临时调用。

awk函数的定义方法如下:

function 函数名(参数表){
函数体
}

在gawk中允许将function省略为func,但其它版本的awk不允许。函数名必须是一个合法的标志符,参数表中可以不提供参数(但在调用函数时函数名后的一对括号仍然是不可缺少的),也可以提供一个或多个参数。与C语言相似,awk的参数也是通过值来传递的。

在 awk中调用函数比较简单,其方法与C语言相似,但awk比C语言更为灵活,它不执行参数有效性检查。换句话说,在你调用函数时,可以列出比函数预计(函 数定义中规定)的多或少的参数,多余的参数会被awk所忽略,而不足的参数,awk将它们置为缺省值0或空字符串,具体置为何值,将取决于参数的使用方 式。

awk函数有两种返回方式:隐式返回和显式返回。当awk执行到函数的结尾时,它自动地返回到调用程序,这是函数是隐式返回的。如果需要在结束之前退出函数,可以明确地使用返回语句提前退出。方法是在函数中使用形如:return 返回值 格式的语句。

例: 下面的例子演示了函数的使用。在这个示例中,定义了一个名为print_header的函数,该函数调用了两个参数FileName和 PageNum,FileName参数传给函数当前使用的文件名,PageNum参数是当前页的页号。这个函数的功能是打印(显示)出当前文件的文件名, 和当前页的页号。完成这个功能后,这个函数将返回下一页的页号。

nawk
>'BEGIN{pageno=1;file=FILENAME
>pageno=print_header(file,pageno);#调用函数print_header
>printf("当前页页号是:%d\n",pageno);
>}

>#定义函数print_header
>function print_header(FileName,PageNum){
>printf("%s %d\n",FileName,PageNum);
>PageNum++;return PageNUm;
>}
>}' myfile

执行这个程序将显示如下内容:

myfile 1
当前页页号是:2

awk高级输入输出

1.读取下一条记录:

awk的next语句导致awk读取下一个记录并完成模式匹配,然后立即执行相应的操作。通常它用匹配的模式执行操作中的代码。next导致这个记录的任何额外匹配模式被忽略。

2.简单地读取一条记录

awk 的 getline语句用于简单地读取一条记录。如果用户有一个数据记录类似两个物理记录,那么getline将尤其有用。它完成一般字段的分离(设置字 段变量$0 FNR NF NR)。如果成功则返回1,失败则返回0(到达文件尾)。如果需简单地读取一个文件,则可以编写以下代码:

例:示例getline的使用

{while(getline==1)
{
#process the inputted fields
}
}

也可以使getline保存输入数据在一个字段中,而不是通过使用getline variable的形式处理一般字段。当使用这种方式时,NF被置成0,FNR和NR被增值。

用 户也可以使用getline<"filename"方式从一个给定的文件中输入数据,而不是从命令行所列内容输入数据。此时,getline将完成 一般字段分离(设置字段变量$0和NF)。如果文件不存在,返回-1,成功,返回1,返回0表示失败。用户可以从给定文件中读取数据到一个变量中,也可以 用stdin(标准输入设备)或一个包含这个文件名的变量代替filename。值得注意的是当使用这种方式时不修改FNR和NR。

另一种使用getline语句的方法是从UNIX命令接受输入,例如下面的例子:

例:示例从UNIX命令接受输入

{while("who -u"|getline)
{
#process each line from the who command
}
}

当然,也可以使用如下形式:

"command" | getline variable

3.关闭文件:

awk中允许在程序中关闭一个输入或输出文件,方法是使用awk的close语句。

close("filename")

filename可以是getline打开的文件(也可以是stdin,包含文件名的变量或者getline使用的确切命令)。或一个输出文件(可以是stdout,包含文件名的变量或使用管道的确切命令)。

4.输出到一个文件:

awk中允许用如下方式将结果输出到一个文件:

printf("hello word!\n")>"datafile"

printf("hello word!\n")>>"datafile"

5.输出到一个命令

awk中允许用如下方式将结果输出到一个命令:

printf("hello word!\n")|"sort-t','"

awk与shell script混合编程

因 为awk可以作为一个shell命令使用,因此awk能与shell批处理程序很好的融合在一起,这给实现awk与shell程序的混合编程提供了可能。 实现混合编程的关键是awk与shell script之间的对话,换言之,就是awk与shell script之间的信息交流:awk从 shell script中获取所需的信息(通常是变量的值)、在awk中执行shell命令行、shell script将命令执行的结果送给awk处 理以及shell script读取awk的执行结果等等。

1.awk读取Shell script程序变量

在awk中我们可以通过“'$变量名'”的方式读取sell scrpit程序中的变量。

例:在下面的示例中,我们将读取sell scrpit程序中的变量Name,该变量存放的是文本myfile的撰写者,awk将打印出这个人名。

$cat writename
:
# @(#)
#
.
.
.
Name="张三" nawk 'BEGIN {name="'Name'";\ printf("\t%s\t撰写者%s\n",FILENAME,name");}\
{...}END{...}' myfile
.
.
.

2.将shell命令的执行结果送给awk处理

作为信息传送的一种方法,我们可以将一条shell命令的结果通过管道线(|)传递给awk处理:

例:示例awk处理shell命令的执行结果

$who -u | awk '{printf("%s正在执行%s\n",$2,$1)}'

该命令将打印出注册终端正在执行的程序名。

3.shell script程序读awk的执行结果

为 了实现shell script程序读取awk执行的结果,我们可以采取一些特殊的方法,例如我们可以用变量名=`awk语句`的形式将awk执行的结果 存放入一个shell script变量。当然也可以用管道线的方法将awk执行结果传递给shell script程序处理。

例:作 为传送消息的机制之一,UNIX提供了一个向其所有用户传送消息的命令wall(意思是write to all写给所有用户),该命令允许向所有工作中 的用户(终端)发送消息。为此,我们可以通过一段shell批处理程序wall.shell来模拟这一程序(事实上比较老的版本中wall就是一段 shell批处理程序:

$cat wall.shell
:
# @(#) wall.shell:发送消息给每个已注册终端
#
cat >/tmp/$$
#用户录入消息文本 who -u | awk '{print $2}' | while read tty
do
cat /tmp/$$>$tty
done

在 这个程序里,awk接受who -u命令的执行结果,该命令打印出所有已注册终端的信息,其中第二个字段是已注册终端的设备名,因此用awk命令析出该设 备名,然后用while read tty语句循环读出这些文件名到变量(shell script变量)tty中,作为信息传送的终结地址。

4.在awk中执行shell命令行----嵌入函数system()

system()是一个不适合字符或数字类型的嵌入函数,该函数的功能是处理作为参数传递给它的字符串。system对这个参数的处理就是将其作为命令处理,也就是说将其当作命令行一样加以执行。这使得用户在自己的awk程序需要时可以灵活地执行命令或脚本。

例:下面的程序将使用system嵌入函数打印用户编制好的报表文件,这个文件存放在名为myreport.txt的文件中。为简约起见,我们只列出了其END部分:

.
.
.
END {close("myreport.txt");system("lp myreport.txt");}

在这个示例中,我们首先使用close语句关闭了文件myreport.txt文件,然后使用system嵌入函数将myreport.txt送入打印机打印。

写 到这里,我不得不跟朋友们说再见了,实在地说,这些内容仍然是awk的初步知识,电脑永远是前进的科学,awk也不例外,本篇所能做的只是在你前行的漫漫 长途中铺平一段小小开端,剩下的路还得靠你自己去走。老实说,如果本文真能给你前行的路上带来些许的方便,那本人就知足了!

附录:

1.awk的常规表达式元字符

\ 换码序列
^ 在字符串的开头开始匹配
$ 在字符串的结尾开始匹配
. 与任何单个字符串匹配
[ABC] 与[]内的任一字符匹配
[A-Ca-c] 与A-C及a-c范围内的字符匹配(按字母表顺序)
[^ABC] 与除[]内的所有字符以外的任一字符匹配
Desk|Chair 与Desk和Chair中的任一个匹配
[ABC][DEF] 关联。与A、B、C中的任一字符匹配,且其后要跟D、E、F中的任一个字符。
* 与A、B或C中任一个出现0次或多次的字符相匹配
+ 与A、B或C中任何一个出现1次或多次的字符相匹配
? 与一个空串或A、B或C在任何一个字符相匹配
(Blue|Black)berry 合并常规表达式,与Blueberry或Blackberry相匹配

2.awk算术运算符

运算符 用途
------------------
x^y x的y次幂
x**y 同上
x%y 计算x/y的余数(求模)
x+y x加y
x-y x减y
x*y x乘y
x/y x除y
-y 负y(y的开关符号);也称一目减
++y y加1后使用y(前置加)
y++ 使用y值后加1(后缀加)
--y y减1后使用y(前置减)
y-- 使用后y减1(后缀减)
x=y 将y的值赋给x
x+=y 将x+y的值赋给x
x-=y 将x-y的值赋给x
x*=y 将x*y的值赋给x
x/=y 将x/y的值赋给x x%=y 将x%y的值赋给x
x^=y 将x^y的值赋给x
x**=y 将x**y的值赋给x

3.awk允许的测试:

操作符 含义

x==y x等于y
x!=y x不等于y
x>y x大于y
x>=y x大于或等于y
xx<=y x小于或等于y?
x~re x匹配正则表达式re?
x!~re x不匹配正则表达式re?

4.awk的操作符(按优先级升序排列)

= 、+=、 -=、 *= 、/= 、 %=
||
&&
> >= < <= == != ~ !~
xy (字符串连结,'x''y'变成"xy")
+ -
* / %
++ --

5.awk内置变量(预定义变量)

说明:表中v项表示第一个支持变量的工具(下同):A=awk,N=nawk,P=POSIX awk,G=gawk

V 变量 含义 缺省值
--------------------------------------------------------
N ARGC 命令行参数个数
G ARGIND 当前被处理文件的ARGV标志符
N ARGV 命令行参数数组
G CONVFMT 数字转换格式 %.6g
P ENVIRON UNIX环境变量
N ERRNO UNIX系统错误消息
G FIELDWIDTHS 输入字段宽度的空白分隔字符串
A FILENAME 当前输入文件的名字
P FNR 当前记录数
A FS 输入字段分隔符 空格
G IGNORECASE 控制大小写敏感0(大小写敏感)
A NF 当前记录中的字段个数
A NR 已经读出的记录数
A OFMT 数字的输出格式 %.6g
A OFS 输出字段分隔符 空格
A ORS 输出的记录分隔符 新行
A RS 输入的记录他隔符 新行
N RSTART 被匹配函数匹配的字符串首
N RLENGTH 被匹配函数匹配的字符串长度
N SUBSEP 下标分隔符 "\034"
阅读(1458) | 评论(0) | 转发(1) |
0

上一篇:sed高级用法

下一篇:sed高级命令助记

给主人留下些什么吧!~~