awk manual-1
上一篇 / 下一篇 2008-06-23 13:51:12 / 个人分类:Shell编程
awk手册
http://linuxfire.com.cn/~lily/awk.html
1.前言
有关本手册:
这是一本awk学习指引,其重点着重于:
l awk适于解决哪些问题?
l awk常见的解题模式为何?
为使读者快速掌握awk解题的模式及特性,本手册系由一些较具代表性的范例及其题解所构成;各范例由浅入深,彼此间相互连贯,范例中并对所使用的awk语法及指令辅以必要的说明.有关awk的指令,函数,...等条列式的说明则收录于附录中,以利读者往后撰写程序时查阅.如此编排,可让读者在短时间内顺畅地学会使用awk来解决问题.建议读者循着范例上机实习,以加深学习效果.
读者宜先具备下列背景:
[a.] UNIX环境下的简单操作及基本概念.
例如:文件编辑,文件复制及管道,输入/输出重定向等概念
[b.] C语言的基本语法及流程控制指令.
(awk指令并不多,且其中之大部分与C语言中之用法一致,本手册中对该类指令之语法及特性不再加以繁冗的说明,读者若欲深究,可自行翻阅相关的C语言书籍)
2.awk概述
为什么使用awk
awk是一种程序语言.它具有一般程序语言常见的功能.
因awk语言具有某些特点,如:使用直译器(Interpreter)不需先行编译;变量无类型之分(Typeless),可使用文字当数组的下标(Associative Array)...等特色.因此,使用awk撰写程序比起使用其它语言更简洁便利且节省时间. awk还具有一些内建功能,使得awk擅于处理具数据行(Record),字段(Field)型态的资料;此外, awk内建有pipe的功能,可将处理中的数据传送给外部的Shell命令加以处理,再将Shell命令处理后的数据传回awk程序,这个特点也使得awk程序很容易使用系统资源.
由于awk具有上述特色,在问题处理的过程中,可轻易使用awk来撰写一些小工具;这些小工具并非用来解决整个大问题,它们只扮演解决个别问题过程的某些角色,可藉由Shell所提供的pipe将数据按需要传送给不同的小工具进行处理,以解决整个大问题.这种解题方式,使得这些小工具可因不同需求而被重复组合及重用(reuse);也可藉此方式来先行测试大程序原型的可行性与正确性,将来若需要较高的执行速度时再用C语言来改写.这是awk最常被应用之处.若能常常如此处理问题,读者可以以更高的角度来思考抽象的问题,而不会被拘泥于细节的部份.
本手册为awk入门的学习指引,其内容将先强调如何撰写awk程序,未列入进一步解题方式的应用实例,这部分将留待UNIX进阶手册中再行讨论.
如何取得awk
一般的UNIX操作系统,本身即附有awk.不同的UNIX操作系统
所附的awk其版本亦不尽相同.若读者所使用的系统上未附有awk,
可透过anonymous ftp到下列地方取得:
phi.sinica.edu.tw:/pub/gnu
ftp.edu.tw:/UNIX/gnu
prep.ai.mit.edu:/pub/gnu
awk如何工作
为便于解释awk程序架构,及有关术语(terminology),先以一个员工薪资档(emp.dat ),来加以介绍.
A125 Jenny 100 210
A341 Dan 110 215
P158 Max 130 209
P148 John 125 220
A123 Linda 95 210
文件中各字段依次为员工ID,姓名,薪资率,及实际工时. ID中的第一码为部门识别码. "A","P"分别表示"组装"及"包装"部门.
本小节着重于说明awk程序的主要架构及工作原理,并对一些重要的名词辅以必要的解释.由这部分内容,读者可体会出awk语言的主要精神及awk与其它语程序言的差异处.为便于说明,以条列方式说明于后.
名词定义
l 数据行: awk从数据文件上读取数据的基本单位.以上列文件emp.dat为例, awk读入的
第一笔数据行是"A125 Jenny 100 210"
第二笔数据行是"A341 Dan 110 215"
一般而言,一个数据行就相当于数据文件上的一行资料. (参考:附录B内建变量"RS" )
l 字段(Field) :为数据行上被分隔开的子字符串.
以数据行"A125 Jenny 100 210"为例,
第一栏第二栏第三栏第四栏"A125" "Jenny" 100 210
一般是以空格符来分隔相邻的字段. (参考:附录D内建变量"FS" )
3.如何执行awk
于UNIX的命令行上键入诸如下列格式的指令: ( "$"表Shell命令行上的提示符号)
$awk 'awk程序'数据文件文件名
则awk会先编译该程序,然后执行该程序来处理所指定的数据文件.
(上列方式系直接把程序写在UNIX的命令行上)
awk程序的主要结构:
awk程序中主要语法是Pattern { Actions},故常见之awk程序其型态如下:
Pattern1 { Actions1 }
Pattern2 { Actions2 }
......
Pattern3 { Actions3 }
Pattern是什么?
awk可接受许多不同型态的Pattern.一般常使用"关系表达式"(Relational expression)来当成Pattern.
例如:
x > 34是一个Pattern,判断变量x与34是否存在大于的关系.
x == y是一个Pattern,判断变量x与变量y是否存在等于的关系.
上式中x >34 , x == y便是典型的Pattern.
awk提供C语言中常见的关系运算符(Relational Operators)如
>, <, >=, <=, ==, !=
此外, awk还提供~ (match)及!~(not match)二个关系运算符(注一).
其用法与涵义如下:
若A为一字符串, B为一正则表达式(Regular Expression)
A ~ B判断字符串A中是否包含能匹配(match)B表达式的子字符串.
A !~ B判断字符串A中是否不包含能匹配(match)B表达式的子字符串.
例如:
"banana" ~ /an/整个是一个Pattern.
因为"banana"中含有可以匹配/an/的子字符串,故此关系式成立(true),整个Pattern的值也是true.
相关细节请参考附录A Patterns,附录E Regular Expression
(注一:)有少数awk论著,把~, !~当成另一类的Operator,并不视为一种Relational Operator.本手册中将这两个运算符当成一种Relational Operator.
Actions是什么?
Actions是由许多awk指令构成.而awk的指令与C语言中的指令十分类似.
例如:
awk的I/O指令: print, printf( ), getline...
awk的流程控制指令: if(...){..} else{..}, while(...){...}...
(请参考附录B --- "Actions" )
awk如何处理Pattern { Actions } ?
awk会先判断(Evaluate)该Pattern的值,若Pattern判断后的值为true (或不为0的数字,或不是空的字符串),则awk将执行该Pattern所对应的Actions.反之,若Pattern之值不为true,则awk将不执行该Pattern所对应的Actions.
例如:若awk程序中有下列两指令
50 > 23 {print "Hello! The word!!" }
"banana" ~ /123/ { print "Good morning !" }
awk会先判断50 >23是否成立.因为该式成立,所以awk将印出"Hello! The word!!".而另一Pattern为"banana" ~/123/,因为"banana"内未含有任何子字符串可match /123/,该Pattern之值为false,故awk将不会印出"Good morning !"
awk如何处理{ Actions }的语法?(缺少Pattern部分)
有时语法Pattern { Actions }中, Pattern部分被省略,只剩{Actions}.这种情形表示"无条件执行这个Actions".
awk的字段变量
awk所内建的字段变量及其涵意如下:
字段变量 | 含义 |
$0 | 一字符串,其内容为目前awk所读入的数据行. |
$1 | $0上第一个字段的数据. |
$2 | $0上第二个字段的数据. |
... | 其余类推 |
读入数据行时, awk如何更新(update)这些内建的字段变量?
当awk从数据文件中读取一个数据行时, awk会使用内建变量$0予以记录.每当$0被改动时(例如:读入新的数据行或自行变更$0,...) awk会立刻重新分析$0的字段情况,并将$0上各字段的数据用$1, $2, ..予以记录.
awk的内建变量(Built-in Variables)
awk提供了许多内建变量,使用者于程序中可使用这些变量来取得相关信息.常见的内建变量有:
内建变量 | 含义 |
NF (Number of Fields) | 为一整数,其值表$0上所存在的字段数目. |
NR (Number of Records) | 为一整数,其值表awk已读入的数据行数目. |
FILENAMEawk | 正在处理的数据文件文件名. |
例如: awk从资料文件emp.dat中读入第一笔数据行
"A125 Jenny 100 210"之后,程序中:
$0之值将是"A125 Jenny 100 210"
$1之值为"A125"
$2之值为"Jenny"
$3之值为100
$4之值为210
$NF之值为4
$NR之值为1
$FILENAME之值为"emp.dat"
awk的工作流程:
执行awk时,它会反复进行下列四步骤.
- 自动从指定的数据文件中读取一个数据行.
- 自动更新(Update)相关的内建变量之值.如: NF, NR, $0...
- 依次执行程序中所有的Pattern { Actions }指令.
- 当执行完程序中所有Pattern { Actions }时,若数据文件中还有未读取的数据,则反复执行步骤1到步骤4.
awk会自动重复进行上述4个步骤,使用者不须于程序中编写这个循环(Loop).
打印文件中指定的字段数据并加以计算
awk处理数据时,它会自动从数据文件中一次读取一笔记录,并会
将该数据切分成一个个的字段;程序中可使用$1, $2,...直接取得
各个字段的内容.这个特色让使用者易于用awk编写reformatter来改变量据格式.
[范例:]以文件emp.dat为例,计算每人应发工资并打印报表.
[分析:] awk会自行一次读入一列数据,故程序中仅需告诉
awk如何处理所读入的数据行.
执行如下命令: ( $表UNIX命令行上的提示符)
$ awk '{ print $2, $3 * $4 }' emp.dat
执行结果如下:
屏幕出现:
Jenny 21000
Dan 23650
Max 27170
John 27500
Linda 19950
[说明:]
UNIX命令行上,执行awk的语法为:
$awk 'awk程序'欲处理的资料文件文件名
本范例中的程序部分为{print $2, $3 * $4}.
把程序置于命令行时,程序之前后须以'括住.
emp.dat为指定给该程序处理的数据文件文件名.
本程序中使用: Pattern { Actions }语法.
Pattern部分被省略,表无任何限制条件.故awk读入每笔数据行后都将无条件执行这个Actions.
print为awk所提供的输出指令,会将数据输出到stdout(屏幕).
print的参数间彼此以"," (逗号)隔开,印出数据时彼此间会以空白隔开. (参考附录D内建变量OFS)
将上述的程序部分储存于文件pay1.awk中.执行命令时再指定awk程序文件之文件名.这是执行awk的另一种方式,特别适用于程序较大的情况,其语法如下:
$ awk -f awk程序文件名数据文件文件名
故执行下列两命令,将产生同样的结果.
$ awk -f pay1.awk emp.dat
$ awk '{ print $2, $3 * $4 }' emp.dat
读者可使用"-f"参数,让awk主程序使用“其它仅含awk函数的文件中的函数”
其语法如下:
$ awk -f awk主程序文件名-f awk函数文件名数据文件文件名
(有关awk中函数的声明与使用于7.4中说明)
awk中也提供与C语言中类似用法的printf()函数.使用该函数可进一步控制数据的输出格式.
编辑另一个awk程序如下,并取名为pay2.awk
{ printf("%6s Work hours: %3d Pay: %5d\n", $2,$3, $3* $4) }
执行下列命令
$awk -f pay2.awk emp.dat
执行结果屏幕出现:
Jenny Work hours: 100 Pay: 21000
Dan Work hours: 110 Pay: 23650
Max Work hours: 130 Pay: 27170
John Work hours: 125 Pay: 27500
Linda Work hours: 95 Pay: 19950
4.选择符合指定条件的记录
Pattern { Action }为awk中最主要的语法.若某Pattern之值为真则执行它后方的Action. awk中常使用"关系表达式" (Relational Expression)来当成Pattern.
awk中除了>, <, ==, != ,...等关系运算符( Relational Operators )外,另外提供~(match),!~(Not Match)二个关系运算符.利用这两个运算符,可判断某字符串是否包含能匹配所指定正则表达式的子字符串.由于这些特性,很容易使用awk来编写需要字符串比对,判断的程序.
[范例:]承上例,
组装部门员工调薪5%,(组装部门员工之ID以"A"开头)
所有员工最后之薪资率若仍低于100,则以100计.
编写awk程序打印新的员工薪资率报表.
[分析] :这个程序须先判断所读入的数据行是否合于指定条件,再进行某些动作.awk中Pattern { Actions }的语法已涵盖这种" if (条件) {动作} "的架构.编写如下之程序,并取名adjust1.awk
$1 ~ /^A.*/ { $3 *= 1.05 } $3<100 { $3 = 100 }
{ printf("%s %8s %d\n", $1, $2, $3)}
执行下列命令:
$awk -f adjust1.awk emp.dat
结果如下:屏幕出现:
A125 Jenny 105
A341 Dan 115
P158 Max 130
P148 John 125
A123 Linda 100
说明:
awk的工作程序是:从数据文件中每次读入一个数据行,依序执行完程序中所有的Pattern{ Action }指令:
$1~/^A.*/ { $3 *= 1.05 }
$3 < 100 { $3 = 100 }
{printf("%s %8s %d\n",$1,$2,$3)}
再从数据文件中读进下一笔记录继续进行处理.
第一个Pattern { Action }是: $1 ~ /^A.*/ { $3 *= 1.05 }
$1 ~ /^A.*/是一个Pattern,用来判断该笔数据行的第一栏是否包含以"A"开头的子字符串.其中/^A.*/是一个Regular Expression,用以表示任何以"A"开头的字符串. (有关Regular Expression之用法参考附录E ).
Actions部分为$3 *= 1.05
$3 *= 1.05与$3 = $3 * 1.05意义相同.运算子"*="之用法则与C语言中一样.此后与C语言中用法相同的运算子或语法将不予赘述.
第二个Pattern { Actions }是: $3 <100 {$3 = 100 }若第三栏的数据内容(表薪资率)小于100,则调整为100.
第三个Pattern { Actions }是: {printf("%s %8s %d\n",$1, $2, $3 )}省略了Pattern(无条件执行Actions),故所有数据行调整后的数据都将被印出.
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 |
我的存档
数据统计
- 访问量: 47787
- 日志数: 70
- 建立时间: 2007-07-05
- 更新时间: 2011-11-08