awk 命令详解教程.docx

上传人:b****8 文档编号:23578874 上传时间:2023-05-18 格式:DOCX 页数:78 大小:64.35KB
下载 相关 举报
awk 命令详解教程.docx_第1页
第1页 / 共78页
awk 命令详解教程.docx_第2页
第2页 / 共78页
awk 命令详解教程.docx_第3页
第3页 / 共78页
awk 命令详解教程.docx_第4页
第4页 / 共78页
awk 命令详解教程.docx_第5页
第5页 / 共78页
点击查看更多>>
下载资源
资源描述

awk 命令详解教程.docx

《awk 命令详解教程.docx》由会员分享,可在线阅读,更多相关《awk 命令详解教程.docx(78页珍藏版)》请在冰豆网上搜索。

awk 命令详解教程.docx

awk命令详解教程

awk手册

 

简体中文版由bones7456()整理.

原文:

应该是http:

//phi.sinica.edu.tw/aspac/reports/94/94011/但是原文很乱.

说明:

之前也是对awk几乎一无所知,无意中看到这篇文章,网上一搜,居然没有像样的简体中文版.有的也是不怎么完整,或者错误一大堆的.于是就顺手整理了下这篇文章.通过整理这篇文章,自己也渐渐掌握了awk的种种用法.

原文可能比较老,有些目前已经不适用的命令有所改动,文中所有命令均在ubuntu7.04下调试通过,用的awk是mawk.

由于本人能力有限,错误和不妥之处在所难免,欢迎多多指正.

lastupdate:

2010-04-16

1.前言

有关本手册:

这是一本awk学习指引,其重点着重于:

●       awk适于解决哪些问题?

●       awk常见的解题模式为何?

为使读者快速掌握awk解题的模式及特性,本手册系由一些较具代表性的范例及其题解所构成;各范例由浅入深,彼此间相互连贯,范例中并对所使用的awk语法及指令辅以必要的说明.有关awk的指令,函数,...等条列式的说明则收录于附录中,以利读者往后撰写程序时查阅.如此编排,可让读者在短时间内顺畅地学会使用awk来解决问题.建议读者循着范例上机实习,以加深学习效果.

 

读者宜先具备下列背景:

[a.]UNIX环境下的简单操作及基本概念.

例如:

文件编辑,文件复制及管道,输入/输出重定向等概念

[b.]C语言的基本语法及流程控制指令.

(awk指令并不多,且其中之大部分与C语言中之用法一致,本手册中对该类指令之语法及特性不再加以繁冗的说明,读者若欲深究,可自行翻阅相关的C语言书籍)

 

2.awk概述

为什么使用awk

awk是一种程序语言.它具有一般程序语言常见的功能.

因awk语言具有某些特点,如:

使用直译器(Interpreter)不需先行编译;变量无类型之分(Typeless),可使用文字当数组的下标(AssociativeArray)...等特色.因此,使用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,

可透过anonymousftp到下列地方取得:

phi.sinica.edu.tw:

/pub/gnu

ftp.edu.tw:

/UNIX/gnu

prep.ai.mit.edu:

/pub/gnu

 

awk如何工作

为便于解释awk程序架构,及有关术语(terminology),先以一个员工薪资档(emp.dat),来加以介绍.

A125Jenny100210

A341Dan110215

P158Max130209

P148John125220

A123Linda95210

文件中各字段依次为员工ID,姓名,薪资率,及实际工时.ID中的第一码为部门识别码."A","P"分别表示"组装"及"包装"部门.

本小节着重于说明awk程序的主要架构及工作原理,并对一些重要的名词辅以必要的解释.由这部分内容,读者可体会出awk语言的主要精神及awk与其它语程序言的差异处.为便于说明,以条列方式说明于后.

名词定义

●       数据行:

awk从数据文件上读取数据的基本单位.以上列文件emp.dat为例,awk读入的

第一笔数据行是"A125Jenny100210"

第二笔数据行是"A341Dan110215"

一般而言,一个数据行就相当于数据文件上的一行资料.(参考:

附录B内建变量"RS")

●       字段(Field):

为数据行上被分隔开的子字符串.

以数据行"A125Jenny100210"为例,

第一栏第二栏第三栏第四栏"A125""Jenny"100210

一般是以空格符来分隔相邻的字段.(参考:

附录D内建变量"FS")

 

3.如何执行awk

于UNIX的命令行上键入诸如下列格式的指令:

("$"表Shell命令行上的提示符号)

$awk'awk程序'数据文件文件名

则awk会先编译该程序,然后执行该程序来处理所指定的数据文件.

(上列方式系直接把程序写在UNIX的命令行上)

awk程序的主要结构:

awk程序中主要语法是Pattern{Actions},故常见之awk程序其型态如下:

Pattern1{Actions1}

Pattern2{Actions2}

......

Pattern3{Actions3}

 

Pattern是什么?

awk可接受许多不同型态的Pattern.一般常使用"关系表达式"(Relationalexpression)来当成Pattern.

例如:

x>34是一个Pattern,判断变量x与34是否存在大于的关系.

x==y是一个Pattern,判断变量x与变量y是否存在等于的关系.

上式中x>34,x==y便是典型的Pattern.

awk提供C语言中常见的关系运算符(RelationalOperators)如

>,<,>=,<=,==,!

=

此外,awk还提供~(match)及!

~(notmatch)二个关系运算符(注一).

其用法与涵义如下:

若A为一字符串,B为一正则表达式(RegularExpression)

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

A!

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

例如:

"banana"~/an/整个是一个Pattern.

因为"banana"中含有可以匹配/an/的子字符串,故此关系式成立(true),整个Pattern的值也是true.

相关细节请参考附录APatterns,附录ERegularExpression

(注一:

)有少数awk论著,把~,!

~当成另一类的Operator,并不视为一种RelationalOperator.本手册中将这两个运算符当成一种RelationalOperator.

 

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!

Theword!

!

"}

"banana"~/123/{print"Goodmorning!

"}

awk会先判断50>23是否成立.因为该式成立,所以awk将印出"Hello!

Theword!

!

".而另一Pattern为"banana"~/123/,因为"banana"内未含有任何子字符串可match/123/,该Pattern之值为false,故awk将不会印出"Goodmorning!

"

 

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-inVariables)

awk提供了许多内建变量,使用者于程序中可使用这些变量来取得相关信息.常见的内建变量有:

内建变量

含义

NF(NumberofFields)

为一整数,其值表$0上所存在的字段数目.

NR(NumberofRecords)

为一整数,其值表awk已读入的数据行数目.

FILENAMEawk

正在处理的数据文件文件名.

 

例如:

awk从资料文件emp.dat中读入第一笔数据行

"A125Jenny100210"之后,程序中:

$0之值将是"A125Jenny100210"

$1之值为"A125"

$2之值为"Jenny"

$3之值为100

$4之值为210

$NF之值为4

$NR之值为1

$FILENAME之值为"emp.dat"

 

awk的工作流程:

执行awk时,它会反复进行下列四步骤.

 

1.自动从指定的数据文件中读取一个数据行.

2.自动更新(Update)相关的内建变量之值.如:

NF,NR,$0...

3.依次执行程序中所有的Pattern{Actions}指令.

4.当执行完程序中所有Pattern{Actions}时,若数据文件中还有未读取的数据,则反复执行步骤1到步骤4.

awk会自动重复进行上述4个步骤,使用者不须于程序中编写这个循环(Loop).

 

打印文件中指定的字段数据并加以计算

awk处理数据时,它会自动从数据文件中一次读取一笔记录,并会

将该数据切分成一个个的字段;程序中可使用$1,$2,...直接取得

各个字段的内容.这个特色让使用者易于用awk编写reformatter来改变量据格式.

[范例:

]以文件emp.dat为例,计算每人应发工资并打印报表.

[分析:

]awk会自行一次读入一列数据,故程序中仅需告诉

awk如何处理所读入的数据行.

执行如下命令:

($表UNIX命令行上的提示符)

 

$awk'{print$2,$3*$4}'emp.dat

执行结果如下:

屏幕出现:

Jenny21000

Dan23650

Max27170

John27500

Linda19950

 

[说明:

]

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-fawk程序文件名数据文件文件名

故执行下列两命令,将产生同样的结果.

$awk-fpay1.awkemp.dat

$awk'{print$2,$3*$4}'emp.dat

 

读者可使用"-f"参数,让awk主程序使用“其它仅含awk函数的文件中的函数”

其语法如下:

$awk-fawk主程序文件名-fawk函数文件名数据文件文件名

(有关awk中函数的声明与使用于7.4中说明)

awk中也提供与C语言中类似用法的printf()函数.使用该函数可进一步控制数据的输出格式.

编辑另一个awk程序如下,并取名为pay2.awk

 

{printf("%6sWorkhours:

%3dPay:

%5d\n",$2,$3,$3*$4)}

执行下列命令

 

$awk-fpay2.awkemp.dat

 

执行结果屏幕出现:

 JennyWorkhours:

100Pay:

21000

  DanWorkhours:

110Pay:

23650

  MaxWorkhours:

130Pay:

27170

 JohnWorkhours:

125Pay:

27500

 LindaWorkhours:

 95Pay:

19950

 

4.选择符合指定条件的记录

Pattern{Action}为awk中最主要的语法.若某Pattern之值为真则执行它后方的Action.awk中常使用"关系表达式"(RelationalExpression)来当成Pattern.

awk中除了>,<,==,!

=,...等关系运算符(RelationalOperators)外,另外提供~(match),!

~(NotMatch)二个关系运算符.利用这两个运算符,可判断某字符串是否包含能匹配所指定正则表达式的子字符串.由于这些特性,很容易使用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-fadjust1.awkemp.dat

结果如下:

屏幕出现:

A125   Jenny105

A341     Dan115

P158     Max130

P148    John125

A123   Linda100

说明:

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.*/是一个RegularExpression,用以表示任何以"A"开头的字符串.(有关RegularExpression之用法参考附录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),故所有数据行调整后的数据都将被印出.

 

5.awk中数组

awk程序中允许使用字符串当做数组的下标(index).利用这个特色十分有助于资料统计工作.(使用字符串当下标的数组称为AssociativeArray)

首先建立一个数据文件,并取名为reg.dat.此为一学生注册的资料文件;第一栏为学生姓名,其后为该生所修课程.

MaryO.S.Arch.Discrete

SteveD.S.AlgorithmArch.

WangDiscreteGraphicsO.S.

LisaGraphicsA.I.

LilyDiscreteAlgorithm

awk中数组的特性

使用字符串当数组的下标(index).

使用数组前不须宣告数组名及其大小.

例如:

希望用数组来记录reg.dat中各门课程的修课人数.

这情况,有二项信息必须储存:

(a)课程名称,如:

"O.S.","Arch."..,共有哪些课程事先并不明确.

(b)各课程的修课人数.如:

有几个人修"O.S."

在awk中只要用一个数组就可同时记录上列信息.其方法如下:

使用一个数组Number[]:

以课程名称当Number[]的下标.

以Number[]中不同下标所对映的元素代表修课人数.

例如:

有2个学生修"O.S.",则以Number["O.S."]=2表之.

若修"O.S."的人数增加一人,则Number["O.S."]=Number["O.S."]+1或Number["O.S."]++.

如何取出数组中储存的信息

以C语言为例,声明intArr[100];之后,若想得知Arr[]中所储存的数据,只须用一个循环,如:

for(i=0;i<100;i++)printf("%d\n",Arr[i]);

即可.上式中:

数组Arr[]的下标:

0,1,2,...,99

数组Arr[]中各下标所对应的值:

Arr[0],Arr[1],...Arr[99]

但awk中使用数组并不须事先宣告.以刚才使用的Number[]而言,程序执行前,并不知将来有哪些课程名称可能被当成Number[]的下标.

awk提供了一个指令,藉由该指令awk会自动找寻数组中使用过的所有下标.以Number[]为例,awk将会找到"O.S.","Arch.",...

使用该指令时,须指定所要找寻的数组,及一个变量.awk会使用该的变量来记录从数组中找到的每一个下标.例如

for(courseinNumber){....}

指定用course来记录awk从Number[]中所找到的下标.awk每找到一个下标时,就用course记录该下标之值且执行{....}中之指令.藉由这个方式便可取出数组中储存的信息.

(详见下例)

[范例:

]统计各科修课人数,并印出结果.

建立如下程序,并取名为course.awk:

{for(i=2;i<=NF;i++)Number[$i]++}

END{for(courseinNumber)printf("%10s%d\n",course,Number[course])}

执行下列命令:

$awk-fcourse.awkreg.dat

执行结果如下:

 Graphics2

     O.S.2

 Discrete3

     A.I.1

     D.S.1

    Arch.2

 Algorithm2

[说明:

]

 

这程序包含二个Pattern{Actions}指令.

{for(i=2;i<=NF;i++)Number[$i]++}

END{for(courseinNumber)printf("%10s%d\n",course,Number[course])}

第一个Pattern{Actions}指令中省

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1