保持快乐,善于表达,敢于创新

awk manual-5

上一篇 / 下一篇  2008-06-23 14:03:06 / 个人分类:Shell编程

12.        附录A ──  Pattern

awk通过判断Pattern之值来决定是否执行其后所对应的Actions.这里列出几种常见的Pattern :

ØBEGIN

BEGINawk的保留字,是一种特殊的Pattern.

BEGIN成立(其值为true)的时机是: "awk程序一开始执行,尚未读取任何数据之前."所以在BEGIN { Actions }语法中,Actions部份仅于程序一开始执行时被执行一次.awk从数据文件读入数据行后, BEGIN便不再成立,故不论有多少数据行,Actions部份仅被执行

一次.

一般常把"与数据文件内容无关""只需执行ㄧ次"的部分置于该Actions(BEGINPattern).

例如:

BEGIN {

FS = "[ \t:]" #于程序一开始时,改变awk切割字段的方式

RS = "" #于程序一开始时,改变awk分隔数据行的方式

count = 100 #设定变量count的起始值

print " This is a title line " #印出一行title

}

....... #其它Pattern { Actions } .....

有些awk程序甚至"不需要读入任何数据行".遇到这情况可把整个程序置于以BEGINPatternActions.

例如:

BEGIN { print " Hello ! the Word ! " }

注意:执行该类仅含BEGIN { Actions }的程序时, awk并不会开启任何数据文件进行处理.

ØEND

ENDawk的保留字,是另一种特殊的Pattern.

END成立(其值为true)的时机与BEGIN恰好相反,:"awk处理完所有数据,即将离开程序时"平常读入数据行时, END并不成立,故其对应的Actions并不被执行;唯有当awk读完所有数据时,Actions才会被执行

注意:不管数据行有多少笔,Actions仅被执行一次.

Ø关系表达式

使用像" A关系运算符B"的表达式当成Pattern.

AB存在所指定的关系(Relation),Pattern就算成立(true).

例如:

length($0) <= 80 { print $0 }

上式中length($0)<= 80是一个Pattern,$0(数据行)之长度小于等于80时该Pattern之值为true,将执行其后的Action (打印该数据行).

 

awk中提供下列关系运算符(Relation Operator)

运算符含意

>大于

<小于

>=大于或等于

<=小于或等于

==等于

!=不等于

~ match

!~ not match

上列关系运算符除~(match)!~(not match)外与C语言中之含意一致.

~(match)!~(match)awk之含意简述如下:

A为一字符串, B为一正则表达式.

A ~B判断字符串A中是否包含能匹配(match)B式样的子字符串.

A !~B判断字符串A中是否未包含能匹配(match)B式样的子字符串.

例如:

$0 ~ /program[0-9]+\.c/ { print $0 }

$0 ~ /program[0-9]+\.c/整个是一个Pattern,用来判断$0(数据行)中是否含有可match /program[0-9]+\.c/的子字符串,$0中含有该类字符串,则执行print (打印该行数据).

Pattern中被用来比对的字符串为$0(如本例),可仅以正则表达式部分表示整个Pattern.

故本例的Pattern部分$0 ~/program[0-9]+\.c/可仅用/program[0-9]+\.c/表之(有关匹配及正则表达式请参考附录E )

Ø正则表达式

直接使用正则表达式当成Pattern;此为$0 ~正则表达式的简写.

Pattern用以判断$0(数据行)中是否含有匹配该正则表达式的子字符串;若含有该成立(true)则执行其对应的Actions.

例如:

/^[0-9]*$/ { print "This line is a integer !" }

$0 ~/^[0-9]*$/ { print "This line is a integer !" }相同

Ø混合Pattern

之前所介绍的各种Patterns,其计算后结果为一逻辑值(True or False).awk中逻辑值彼此间可通过&&(and), ||(or),  !(not)结合成一个新的逻辑值.故不同Patterns彼此可通过上述结合符号来结合成一个新的Pattern.如此可进行复杂的条件判断.

:

FNR >= 23 && FNR <= 28 { print "     " $0 }

上式利用&& (and)将两个Pattern求值的结果合并成一个逻辑值.

该式将数据文件中2328向右移5(先输出5个空白字符)后输出.

( FNRawk的内建变量,请参考附录D )

ØPattern1 , Pattern2

遇到这种Pattern, awk会帮您设立一个switch(flag).

awk读入的数据行使得Pattern1成立时, awk会打开(turn on)switch.

awk读入的数据行使得Pattern2成立时, awk会关上(turn off)这个switch.

Pattern成立的条件是:

当这个switch被打开(turn on)(包括Pattern1,Pattern2成立的情况)

:

FNR >= 23 && FNR <= 28 { print "     " $0 }

可改写为

FNR == 23 , FNR == 28 { print "     " $0 }

:

FNR >= 23, awkturn on这个switch;因为随着数据行的读入, awk不停的累加FNR.FNR = 28, Pattern2 (FNR == 28)便成立,这时awk会关上这个switch.

switch打开的期间, awk会执行  print "     " $0

( FNRawk的内建变量,请参考附录D )

 

13.        附录B ── Actions

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

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

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

Ø流程控制指令

l       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[ ]前后括住表示该部分可视需要而予加入或省略.

l       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将持续进行其后的语句.

l       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部分至少会执行一次.

l       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", 12 .

(b)以这个for指令,所查找出的下标之值彼此间并无任何次续关系.

(c)5节中有该指令的使用范例,及解说.

l       for Statement指令()

语法:

for(expression1; expression2; expression3) statement 

范例:

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

说明:

(a)上列范例用以计算1加到10的总和.

(b)expression1 常用于设定该for循环的起始条件,如上例中的i=1

   expression2用于设定该循环的停止条件,如上例中的i <= 10

   expression3常用于改变counter之值,如上例中的i++

 

l       break指令

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

范例:

while(  getline < "datafile" > 0 )

{

    if( $1 == 0 )

        break

    else

        print $2 / $1

}

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

l       continue指令

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

范例:

for( index in X_array)

{

    if( index !~ /[0-9]+/ )  continue

    print "There is a digital index", index

}

上例中若index不为数字则执行continue,故将略过(不执行)其后的指令.

需留心continuebreak的差异:执行continue只是掠过其后未执行的statement,但并未跳离开该循环.

l       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 })执行起.

l       exit指令

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

 

Øawk中的I/O指令

l       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)printprintf两个指令,其后可使用>>>将输出到stdout的数据重定向到其它文件, 7.1节中有完整的

l       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(请参考附录D內建变量OFS)隔开. OFS之值一般內定为"一个空格"

(d)上式中,字串"Ave Score :"与变量ave之间并未以","隔开, awk会将这两者先当成字串concate在一起(变成"Ave Score :89"),再予打印

l       getline指令

语法

语法

由何处读取数据

数据读入后置于

getline var < file

所指定的file

变量var(var省略时,表示置于$0)

getline var

pipe变量

变量var(var省略时,表示置于$0)

getline var

注一

变量var(var省略时,表示置于$0)

getline一次读取一行资料,若读取成功则return 1,若读取失败则return -1,若遇到文件结束(EOF),return 0

l       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中的数据;并未立即执行,这点与Unixpipe的用法不尽相同.

(c)最后希望於文件data.rpt的末尾处加上一行"There are.....".但此时, Shell尚未执行"sort -k 1 > data.rpt"故各数据行排序后的IDSalary等数据尚未写入data.rpt.所以得命令awk提前先通知Shell执行命令"sort -k 1 > data.rpt"来处理pipe中的资料. awk中这个动作称为close pipe.是由执行close ( "shell command" )来完成.需留心close( )指令中的shell command

需与"|"后方的shell command完全相同(一字不差),较佳的方法是先以该字串定义一个简短的变量,程序中再以此变量代替该shell command  


TAG:

 

评分:0

我来说两句

Open Toolbar