awk manual-5
上一篇 / 下一篇 2008-06-23 14:03:06 / 个人分类:Shell编程
12. 附录A ── Pattern
awk通过判断Pattern之值来决定是否执行其后所对应的Actions.这里列出几种常见的Pattern :
ØBEGIN
BEGIN为awk的保留字,是一种特殊的Pattern.
BEGIN成立(其值为true)的时机是: "awk程序一开始执行,尚未读取任何数据之前."所以在BEGIN { Actions }语法中,其Actions部份仅于程序一开始执行时被执行一次.当awk从数据文件读入数据行后, BEGIN便不再成立,故不论有多少数据行,该Actions部份仅被执行
一次.
一般常把"与数据文件内容无关"与"只需执行ㄧ次"的部分置于该Actions(以BEGIN为Pattern)中.
例如:
BEGIN {
FS = "[ \t:]" #于程序一开始时,改变awk切割字段的方式
RS = "" #于程序一开始时,改变awk分隔数据行的方式
count = 100 #设定变量count的起始值
print " This is a title line " #印出一行title
}
....... #其它Pattern { Actions } .....
有些awk程序甚至"不需要读入任何数据行".遇到这情况可把整个程序置于以BEGIN为Pattern的Actions中.
例如:
BEGIN { print " Hello ! the Word ! " }
注意:执行该类仅含BEGIN { Actions }的程序时, awk并不会开启任何数据文件进行处理.
ØEND
END为awk的保留字,是另一种特殊的Pattern.
END成立(其值为true)的时机与BEGIN恰好相反,为:"awk处理完所有数据,即将离开程序时"平常读入数据行时, END并不成立,故其对应的Actions并不被执行;唯有当awk读完所有数据时,该Actions才会被执行
注意:不管数据行有多少笔,该Actions仅被执行一次.
Ø关系表达式
使用像" A关系运算符B"的表达式当成Pattern.
当A与B存在所指定的关系(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求值的结果合并成一个逻辑值.
该式将数据文件中第23行到28行向右移5格(先输出5个空白字符)后输出.
( FNR为awk的内建变量,请参考附录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时, awk就turn on这个switch;因为随着数据行的读入, awk不停的累加FNR.当FNR = 28时, Pattern2 (FNR == 28)便成立,这时awk会关上这个switch.
当switch打开的期间, awk会执行 print " " $0
( FNR为awk的内建变量,请参考附录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", 1及2 .
(b)以这个for指令,所查找出的下标之值彼此间并无任何次续关系.
(c)第5节中有该指令的使用范例,及解说.
l 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++
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,故将略过(不执行)其后的指令.
需留心continue与break的差异:执行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)print及printf两个指令,其后可使用>或>>将输出到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中的数据;并未立即执行,这点与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 ( "shell command" )来完成.需留心close( )指令中的shell command
需与"|"后方的shell command完全相同(一字不差),较佳的方法是先以该字串定义一个简短的变量,程序中再以此变量代替该shell command
TAG:
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | 3 | 4 | ||||||
5 | 6 | 7 | 8 | 9 | 10 | 11 | |||
12 | 13 | 14 | 15 | 16 | 17 | 18 | |||
19 | 20 | 21 | 22 | 23 | 24 | 25 | |||
26 | 27 | 28 | 29 | 30 | 31 |
我的存档
数据统计
- 访问量: 47831
- 日志数: 70
- 建立时间: 2007-07-05
- 更新时间: 2011-11-08