Chinaunix首页 | 论坛 | 博客
  • 博客访问: 512546
  • 博文数量: 119
  • 博客积分: 5054
  • 博客等级: 大校
  • 技术积分: 1305
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-03 13:13
文章分类

全部博文(119)

文章存档

2011年(4)

2010年(115)

我的朋友

分类:

2010-01-03 20:53:52

Actions 是由下列指令(statement)所组成 :

  • 表达式 ( function calls, assignments..)
  • print 表达式列表
  • printf( 格式化字符串, 表达式列表)
  • if( 表达式 ) 语句 [else 语句]
  • while( 表达式 ) 语句
  • do 语句 while( 表达式)
  • for( 表达式; 表达式; 表达式) 语句
  • for( variable in array) 语句
  • delete
  • break
  • continue
  • next
  • exit [表达式]
  • 语句

awk 中大部分指令与 C 语言中的用法一致, 此处仅介绍较为常用或容易混淆的指令的用法.

流程控制指令

if 指令
语法:
if (表达式) 语句1 [else 语句2 ]
范例 :

if( $1 > 25 )
print "The 1st field is larger than 25"
else print "The 1st field is not larger than 25"

(a)与 C 语言中相同, 若 表达式 计算(evaluate)后之值不为 0 或空字符串, 则执行 语句1; 否则执行 语句2.
(b)进行逻辑判断的表达式所返回的值有两种, 若最后的逻辑值为true, 则返回1, 否则返回0.
(c)语法中else 语句2 以[ ] 前后括住表示该部分可视需要而予加入或省略.

while指令
语法 :
while( 表达式 ) 语句
范例 :

while( match(buffer,/[0-9]+\.c/ ) ){
print "Find :" substr( buffer,RSTART, RLENGTH)
buff = substr( buffer, RSTART + RLENGTH)
}

上列范例找出 buffer 中所有能匹配 /[0-9]+.c/(数字之后接上 “.c”的所有子字符串).
范例中 while 以函数 match( )所返回的值做为判断条件. 若buffer 中还含有匹配指定条件的子字符串(match成功), 则 match()函数返回1,while 将持续进行其后的语句.

do-while指令
语法 :
do 语句 while(表达式)
范例 :

do{
print "Enter y or n ! "
getline data
} while( data !~ /^[YyNn]$/)

(a) 上例要求用户从键盘上输入一个字符, 若该字符不是Y, y, N, 或 n则会不停执行该循环, 直到读取正确字符为止.
(b)do-while 指令与 while 指令 最大的差异是 : do-while 指令会先执行statement而后再判断是否应继续执行. 所以, 无论如何其 statement 部分至少会执行一次.

for Statement 指令(一) 
语法 :
for(variable in array ) statement
范例 : 执行下列命令

awk '
BEGIN{
X[1]= 50; X[2]= 60; X["last"]= 70
for( any in X )
printf("X[%s] = %d\n", any, X[any] )
}'

结果输出 :

X[last] = 70
X[1] = 50
X[2] = 60

(a)这个 for 指令, 专用以查找数组中所有的下标值, 并依次使用所指定的变量予以记录. 以本例而言, 变量 any 将逐次代表 “last”, 1 及2 .
(b)以这个 for 指令, 所查找出的下标之值彼此间并无任何次续关系.
(c)第5节中有该指令的使用范例, 及解说.

for Statement 指令(二)
语法 :
for(expression1; expression2; expression3) statement
范例 :

for(i=1; i< =10; i++)  sum = sum + i

[说明 :]
(a)上列范例用以计算 1 加到 10 的总和.
(b)expression1 常用于设定该 for 循环的起始条件, 如上例中的 i=1
expression2 用于设定该循环的停止条件, 如上例中的 i <= 10
expression3 常用于改变 counter 之值, 如上例中的 i++

break 指令
break 指令用以强迫中断(跳离) for, while, do-while 等循环.
范例 :

while(  getline < "datafile" > 0 )
{
    if( $1 == 0 )
        break
    else
        print $2 / $1
}

上例中, awk 不断地从文件 datafile 中读取资料, 当$1等于0时,就停止该执行循环.

continue 指令
循环中的 statement 进行到一半时, 执行 continue 指令来略过循环中尚未执行的statement.
范例 :

for( index in X_array)
{
    if( index !~ /[0-9]+/ )  continue
    print "There is a digital index", index
}

上例中若 index 不为数字则执行 continue, 故将略过(不执行)其后的指令.
需留心 continue 与 break 的差异 : 执行 continue 只是掠过其后未执行的statement, 但并未跳离开该循环.

next 指令
执行 next 指令时, awk 将掠过位于该指令(next)之后的所有指令(包括其后的所有Pattern { Actions }), 接著读取下一笔数据行,继续从第一个 Pattern {Actions} 执行起.
范例 :

/^[ \t]*$/  {  print "This is a blank line! Do nothing here !"
    next
}
$2 != 0 { print $1, $1/$2 }

上例中, 当 awk 读入的数据行为空白行时( match /^[ \]*$/ ),除打印消息外只执行 next, 故 awk 将略过其后的指令, 继续读取下一笔资料, 从头(第一个 Pattern { Actions })执行起.

exit 指令
执行 exit 指令时, awk将立刻跳离(停止执行)该awk程序.

awk 中的 I/O 指令

printf 指令
该指令与 C 语言中的用法相同, 可借由该指令控制资料输出时的格式.
语法 :
printf("format", item1, item2,.. )
范 例 :

id = "BE-2647";  ave = 89
printf("ID# : %s   Ave Score : %d\n", id, ave)

(a)结果印出 :

ID# : BE-2647   Ave Score : 89

(b)format 部分是由 一般的字串(String Constant) 及 格式控制字符(Formatcontrol letter, 其前会加上一个%字符)所构成. 以上式为例"ID# : " 及 " Ave Score : " 为一般字串. %s 及 %d 为格式控制字符.
(c)打印时, 一般字串将被原封不动地打印出来. 遇到格式控制字符时,则依序把 format后方之 item 转换成所指定的格式后进行打印.
(d)有关的细节, 读者可从介绍 C 语言的书籍上得到较完整的介绍.
(e)print 及 printf 两个指令, 其后可使用 > 或 >> 将输出到stdout 的数据重定向到其它文件

print 指令
范 例 :

id = "BE-267";  ave = 89
print "ID# :", id, "Ave Score :"ave

(a)结果印出 :

ID# : BE-267 Ave Score :89

(b)print 之后可接上字串常数(Constant String)或变量. 它们彼此间可用"," 隔开.
(c)上式中, 字串 "ID# :" 与变量 id 之间使用","隔开, 打印时两者之间会以自动 OFS(请参考 awk 之內建变量 OFS) 隔开. OFS 之值一般內定为 "一个空格"
(d)上式中, 字串 "Ave Score :" 与变量ave之间并未以","隔开, awk会将这两者先当成字串concate在一起(变成"Ave Score :89")后,再予打印

getline 指令
语法

注一 : 当 Pattern 为 BEGIN 或 END 时, getline 将由 stdin 读取数据, 否则由awk正处理的数据文件上读取数据.
getline 一次读取一行资料, 若读取成功则return 1,若读取失败则return -1, 若遇到文件结束(EOF), 则return 0

close 指令
该指令用以关闭一个打开的文件, 或 pipe (见下例)
范 例 :

BEGIN {  print "ID #   Salary" > "data.rpt" }
{  print $1 , $2 * $3  | "sort -k 1 > data.rpt" }
END{  close( "data.rpt" )
    close( "sort -k 1 > data.rpt" )
    print " There are", NR, "records processed."
}

[说 明 :]
(a)上例中, 一开始执行 print "ID # Salary" > "data.rpt" 指令来输出一行抬头. 它使用 I/O Redirection ( > )将数据转输出到data.rpt,故此时文件 data.rpt 是处於 Open 状态.
(b)指令 print $1, $2 * $3 不停的将输出的资料送往 pipe(|), awk 在程序将结束时才会呼叫 shell 使用指令 "sort -k 1 > data.rpt" 来处理 pipe 中的数据; 并未立即执行, 这点与 Unix 中pipe的用法不尽相同.
(c)最后希望於文件 data.rpt 的末尾处加上一行 "There are.....".但此时, Shell尚未执行 "sort -k 1 > data.rpt" 故各数据行排序后的 ID 及 Salary 等数据尚未写入data.rpt. 所以得命令 awk 提前先通知 Shell 执行命令 "sort -k 1 > data.rpt" 来处理 pipe 中的资料. awk中这个动作称为 close pipe(close pipe 以提前先通知Shell执行相应的 shell command). 是由执行 close ( "shell command" )来完成. 需留心 close( )指令中的 shell command
需与"|"后方的 shell command 完全相同(一字不差)(只有完全相同,awk才能识别二者是同一个 pipe 而不是两个不同的 pipe), 较佳的方法是先以该字串定义一个简短的变量, 程序中再以此变量代替该shell command
(d)为什么执行 close("data.rpt") ? 因为 sort 完后的资料也将写到data.rpt,而该文件正为awk所打开使用(write)中, 故awk程式中应先关闭data.rpt. 以免造成因二个 processes 同时打开一个文件进行输出(write)所产生的错误.

system 指令
该指令用以执行 Shell上的 command.
范 例 :

DataFile = "invent.rpt"
system( "rm " DataFile )  #注:rm后面有一个空格

[说明 :]
(a)system("字符串")指令接受一个字符串当成Shell的命令. 上例中, 使用一个字串常数"rm " 连接(concate)一个变量 DataFile 形成要求 Shell 执行的命令.Shell 实际执行的命令为 "rm invent.rpt".

"|" pipe指令
"|" 配合 awk 输出指令, 可把 output 到 stdout 的资料继续转送给Shell 上的某一命令当成input的资料.
"|" 配合 awk 的getline 指令, 可呼叫 Shell 执行某一命令, 再以 awk 的 getline 指令将该命令的所产生的资料读进 awk 程序中.
范 例 :

{ print $1, $2 * $3  | "sort -k 1 > result" }
"date" |  getline  Date_data

awk 释放所占用的记忆体的指令

awk 程式中常使用数组(Array)来记忆大量数据, delete 指令便是用来释放数组中的元素所占用的内存空间.
范 例 :

for( any in X_arr )
    delete X_arr[any]

读者请留心, delete 指令一次只能释放数组中的一个元素.

其他

awk 中的数学运算符(Arithmetic Operators)
+(加), -(減), *(乘), /(除), %(求余数), ^(指数) 与 C 语言中用法相同

awk 中的赋值运算符(Assignment Operators)
=, +=, -=, *= , /=, %=, ^=
x += 5 的意思为 x = x + 5, 其余类推.

awk 中的条件运算符(Conditional Operator)
语 法 :
判断条件 ? value1 : value2
若 判断条件 成立(true) 则返回 value1, 否则返回 value2.

awk 中的逻辑运算符(Logical Operators)
&&( and ), ||(or), !(not)
Extended Regular Expression 中使用 "|" 表示 or 请勿混淆.

awk 中的关系运算符(Relational Operators)
>, >=, <, < =, ==, !=, ~, !~

awk 中其它的运算符
+(正号), -(负号), ++(Increment Operator), - -(Decrement Operator)

awk 中各运算符的运算级
按优先高低排列:

$ (栏位运算元, 例如 : i=3; $i表示第3栏)

^ (指数运算)

+ ,- ,! (正,负号,及逻辑上的 not)

* ,/ ,% (乘,除,余数)

+ ,- (加,減)

>, > =,< , < =, ==, != (关系运算符)

~, !~ (match, not match)

&& (逻辑上的 and)

|| (逻辑上的 or )

? : (条件运算符)

= , +=, -=,*=, /=, %=, ^= (赋值运算符)

阅读(753) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~