AWK 学习笔记

原创:http://blog.csdn.net/skydreamer01/article/details/3600628

AWK学习笔记

1 AWK简介

    AWK是Alfred V.Aho, Peter J.Weinberger,Brian W.Kerninghan三人在1977设计和实施的,最初是为了试验Unix中的grep和sed工具怎样可以一般化地在文本之外还能处理数据(grep和sed主要是文本处理工具,但AWK同时善于处理文本与数据)。AWK名字的来源是创造此语言的三个人的名字首字母缩写。它的主要来源是grep, sed和C。后继者主要有Perl。

    AWK非常适合于处理格式化的文本和数据,比如改变数据的格式、验证其合法性、寻找某些属性的项、数字求和、输出数据报表等。数据的结构化越强,使用AWK会越方便。相比于sed,它有字段(sed只有行而没有内置的字段模型)和数字处理功能。相比于C和Perl,由于它自动化了某些处理流程(比如读取文件和分割字段),可以使得某些任务以比C和Perl少得多的代码来完成。

2 AWK编程模型

AWK程序的基本使用语法如下:

awk [-v var=value-Fre 'pattern { action }' var=value datafile(s)
awk [-v var=value-Fre -f scriptfile  var=value datafile(s)

用命令行与用脚本文件(scriptfie)是等价的。一般来说,若pattern、action的代码量比较大,倾向于使用脚本文件。

 对于以上语法说明如下:

l         -v 选项定义的变量在脚本运行之前即存在,可以在脚本的BEGIN流程中被调用;

l         命令行参量(不用-v定义的)只有到输入的第一行读入时才有效,即其在BEGIN流程中无效;

l         -F选项将字段分割符(FS)设为一个正则表达式re;

l         datafile(s)可以是单个文件,也可以是多个文件,可使用正则表达式)。如果用“-”(不包括引号)表示从命令行输入。

l         命令行输入‘pattern{action}’时单引号是必不可少的!不要忘记。pattern和action都是可选的,但是不能都省略。省略pattern时默认匹配所有行;省略action时默认为输出整行。为了分别pattern和action, action需要用{}括起来。

脚本文件的一般格式为:

BEGIN{

 

}

pattern1 { action1 }

pattern2 { action2 }

END{

}

这也说明了AWK的编程模型:程序开始处理BEGIN流程(一般是设置分隔符、定义变量以及输出信息行等),然后进入主循环,读入数据每一行,本行数据设为$0, 行数为NR(某一文件的行数为FNR),同时根据FS变量将$0切分为NF个字段,分别用$1,$2,…,$NF标识。程序对每一行用pattern进行匹配,若匹配上则运行action。在所有行处理完后, 程序将

处理END流程(一般是进行后期处理,输出综合结果等)。

  说明:

l         程序默认的字段分割符(FS)是“[ /t]+”(Tab或空格),输出分割符(OFS)是“ ”,(空格),默认记录分隔符(RS)是“/n”,可根据需要在命令行或BEGIN中修改;

l         pattern可以是以下四种格式:

(1)       表达式(expression). 在表达式为真时执行action.

(2)       正则表达式(/regular expression/), 正则表达式匹配上时执行action.

(3)       复合模式(compound pattern),用 &&(AND), ||(OR),!(NOT)和括号组合出的模式,组合模式为真时执行action.

(4)       范围模式(pattern1,pattern2),从pattern1匹配上的行,直到pattern2匹配上的行,包括这两行。如果pattern2一直没有匹配上,则到文件的末尾。

l         action默认一行一条指令,可包括多行。如果需要在一行中包括多个语句,需要用分号(;)分割开。但是一行一个语句则不需要加分号。这里有与C语言相同又有不同的地方,请注意区别。

常量与转义符

AWK的常量有字符由字符串常量与数值常量组成,字符串常量含引号,而数值常量没有。

AWK的转义符如下:

符号

描述

/a

警告字符,通常是 ASCII BEL字符

/b

退行

/f

Formfeed

/n

换行

/r

回车

/t

TAB

/ddd

八进制

/c

任何字符 c 比如/"代表"

4. 变量

  AWK的变量包括用户定义变量(User-defined Variables)、系统变量(System Variables)和字段变量(Field Variables)

   分别说明如下:

 4.1用户定义变量

   AWK的变量不需要声明,也不需要初始化,直接使用。每一个变量同时有一个字符值和数值,AWK根据上下文环境决定作为数值或字符串处理,这是AWK极其独特之处。AWK自动将变量初始化为空值,如果用作数字将作为0。如果需要强制使用字符串,可使用number “”(空格在AWK中是字符串连接符),若需要强制用作数值,可以用 string + 0。

   另外应注意,在AWK中,$表示字段,用户变量不需要加$,这是AWK与shell或者Perl不同之处!在shell中,变量定义时不加$,再次引用时则需要用$,而在Perl中,无论定义和引用时都需要加$(Perl中$表示标量,另有@和%符号表示数组和Hash变量)。

4.2系统变量

 AWK中包括两种系统变量:默认值可被改变的变量和处理过程中变量。AWK的系统变量列表如下:

变量

             意  义

         默认值

FS

字段分割符

“[ /t]+”

OFS

输出字段分隔符

       “ ”

RS

记录分割符

        ”/n”

ORS

输出记录分隔符

        ”/n”

OFMT

输出数字格式

”%.6g”

CONVFMT

控制数值向字符串转换

      ”%.6g”

 

 

 

NF

字段数

-

NR

当前输入记录数(总数),只有到END时,NR才等于总记录数

-

FNR

当前文件的相对记录数

 

FILENAME

当前输入文件名

 

ARGC

命令行参数数目

 

ARGV

命令行参数数组

 

ARGIND

当前处理文件的ARGV指数,FILENAME==ARGV[ARGIND]总是真的

 

ENVIRON

环境变量数组

 

RSTART

match()匹配到的初始位置

 

RLENGTH

match()匹配到的字符串长度

 

SUBSEP

数组分隔符。将(I,J) 转换为 I SUBSEP J, 模拟多维数组用

 

ERRNO #

在getline时遇到错误的字符串

 

PROCINFO

awk进程信息数组,指标可以使egid,

euid, gid ,pgrpid, pid, ppid, uid, version

 

RT #

每一条记录读入时RS匹配到的字符串

 

 

 注意

l         ARGV数组由ARGV[0] ,…,ARGV[ARGC-1]组成,第一个元素指标是0而不是1。这与AWK中的一般数组不同,而与C一致。

l         ENVIRON数组在shell与AWK的交互中非常有用。

4.3字段变量

从$1,$2一直到$NF,整行用$0标识。注意,如果$0被赋予新值,所有的$1, $2,..和NF都会被重新计算。同样,若$i,被改变,$0将用OFS重新计算。

数组

AWK提供一维数组来存储字符串和数值。数组和数组元素不需要声明,也不需要指定元素个数。AWK特别之处是数组下标总是字符串型的,所以AWK数组总是关联数组(Associative Arrays),相当于Perl的Hash Array。这一点是AWK区别于C及Perl之处。C的数组下标是整数,Perl分别普通数组和Hash数组。

遍历数组的命令是:

for (variable in array)

       statement

注意数组下标的输出次序是依赖于AWK的实现的!

测试数组中是否存在某元素的命令是:

if ( subscript in A )

注意如果用if (A[subscript] == “” ) 命令,将可能创建一个新元素!

删除数组元素的命是:delete array[subscript]

用 for ( i in array) delete array[i] ; 可以删除所的有元素,但是新版的gawk可以用简单的delete array;命令删除整个数组。

AWK的多维数组是用一维数组来模拟的。比如,可以用

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

       for (j = 1; j <=10; j++)

            arr[i, j ] = 0

 if ((i, j) in arr) 方式来使用多维数组。AWK实际用arr[i SUBSEP j]来代替arr[i,j]。

 如果要实现多维数组的循环,可以采取以下方式:

 for (k in arr) {

      split(k, x, SUBSEP)

      i=x[1]

      j=x[2]

      …(i,j)

}

 

操作符

AWK的操作符基本与C语言相同,但也有些例外。按优先级从低至高列表如下:

操 作

符 号

说 明

赋值

= += -= *= /= %= ^=

^=是特别的操作符,C没有

 条件

?:

 

 逻辑或

||

 

  逻辑与

&&

 

数组元素

 in

 if (i in a )

匹配

~  !~

C没有

关系

< <= == != >= >

 

字符串连接

(blank)

“a” “ab” (=”abc”)

加减

+ -

 

乘除求模

* / %

 

单目加减

+ -

-x 正负

逻辑非

!$1

开方

^   (**)

有些现代版本的awk可以用**

自加、自减

++  --

++x  x++

字段运算符

$

$i 第i字段

括号

()

 

 

流程控制

AWK的流程控制基本沿用C的流程控制语句,但是没有do until, switch语句。AWK的流程控制语句如下:

{ statement }

if (expression) statement

if (expression ) statement1 else statment2

while (expression ) statement

for(expression1; expression2;expression3) statement

do statement while (expression)

for (variable in array) statement (这是AWK特别的对于数组中每个变量循环)

break (退出while for do循环)

continue (下一while for do 循环)

next (AWK特别的指令,开始进入下一主输入循环,处理下一行记录,非常有用)

exit

exit expression (马上进入END流程;如果在END流程内,结束程序,以expression值为返回值)

函数

AWK的函数包括系统函数和自定义函数。系统函数又可分为算术函数和字符串函数

8.1 算术函数

函 数

说 明

 

 

cos(x)

 

sin(x)

 

int(x)

求整,截去而不是四舍五入

log(x)

 

exp(x)

 

sqrt(x)

 

atan2(y,x)

 Argtan(y/x)

rand()

 

srand()

 

 

8.2 字符串函数

函 数

说 明

index(s,t)

返回t在s中的第一个位置,如果没找到返回0

length(s)

返回s的字符个数

substr(s,p)

返回s中从p开始的所有字符串

substr(s,p,n)

返回s中从p开始的n个字符

gsub(r,s)

替换$0中所有的正则表达式r为字符串s,返回替换数

gsub(r,s,t)

替换字符串t中所有的正则表达式r为字符串s

sub(r,s)

替换$0中左边最长的匹配r的子串

sub(r,s,t)

替换t中左边最长的匹配r的子串

split(s,a)

用FS切割字符串s为数组a,返回字段数

split(s,a,fs)

用fs切割字符串s为数组a,返回字段数

spintf(fmt,expr-list)

格式化输出

match(s,r[,array])

搜索s,匹配r,设置变量RSTART和RLENGTH

strtonum(str)

GAWK扩展,返回str的数组,可认八进制(0开头)和十六进制(0x开头)

asort(source|,desc)

GAWK扩展,对数组内容排序,若指定desc,拷贝排序内容到desc,source,返回元素个数

asorti(source|,desc)

GAWK扩展。按指标进行排序

tolower(string)

转换为小写

toupper(string)

转换为大写

dcgettext(string[,domain],

[,category])

GAWK国际化函数

dcngettext(string1,string2,

number[,domain][,category]

[,category])

GAWK国际化函数

bindtextdomain(directory

[,domain]

指定信息转换信息的目录

 

8.3 字节处理函数

函 数

说 明

and(v1,v2)

GAWK扩展,与

or(v1,v2)

GAWK扩展,或

xor(v1,v2)

GAWK扩展,异或

compl(val)

GAWK扩展,val的位补函数

lshift(val,count)

GAWK扩展,左移

rshift(val,count)

GAWK扩展,右移

8.4 时间函数

函 数

说 明

systime()

GAWK扩展,timestamp,1970年开始的时间戳

mktime(datespec)

将“YYYY MM DD HH MM SS [DST]”格式的string转化为时间戳

strftime(format

[,timestamp])

转化timestamp为字符串,默认format是“%a %b %d %H:%M:%S %Z %Y”,格式与ISO C 1999的定义一致。

8.5自定义函数

用户定义函数的格式是:

function name(parameter-list){

    statement

}

AWK自定义函数的变量是带值传递,数组是以引用方式传递。另一特别的地方是没在参数列表的变量是全局的。因此定义函数私有变量的方式是将其将入到变量列表中。

输入输出

9.1输出

AWK的输出语句如下:

语句

说 明

print

在标准输出输出 $0

print expression, expression, …

以OFS分隔输出expressions

print expression, expression, … >filename

输出到文件filename中

print expression, expression, … >>filename

追加到文件filename中

print expression, expression, … |command

输出到command的标准输入中

printf(format,expression, expression, …)

带格式输出

printf(format,expression, expression, …) >filename

带格式输出

printf(format,expression, expression, …) >>filename

带格式输出

printf(format,expression, expression, …) |command

带格式输出

close(filename),  close(command)

中断print与filename或command的联系

system(command)

执行任务command

其中printf的格式定义与C相同。

9.2输入

AWK的输入有命令行文件输入,也有通过getline函数输入。getline函数的使用方法是:

语 句

设 置

getline

$0, NF, NR, FNR

getline var

var, NR, FNR

getline <file

$0, NF

getline var <file

Var

cmd |getline

$0, NF

cmd |getline var

var

注意:while(getline <”file”) 是危险的使用循环的方式,可能进入死循环(如果”file”不存在的话。安全的使用方式是 while( getline <”file” > 0)。

 

10 总结

AWK适用于管理小型的个人的数据库、生成报表、验证数据的合法性、生成索引和进行其它文本准备工作以及试验算法。GAWK可以很容易地获取位和字段数据、数据排序以及进行简单的网络通信[2]。尽管AWK是一种小众语言,但是其在格式化数据的处理方面至今起着不可替代的作用。

11 参考文献

【1】       Alfred V.Aho, Brian W.Kerninghan and Peter J.Weinberger. The AWK Programming Language. Addison-Wesley Publishing Company. 1988

【2】       Dale Dougherty and Arnold Robbins. Sed & Awk, 2nd edition. O’Reilly. 1997

【3】       Arnold Robbins. Effective AWK Programming, 3rd edition. O’Reilly. 2001

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值