您的位置:首页 > 运维架构 > Linux

AWK 学习笔记

2013-12-06 19:50 232 查看

原创: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语言相同又有不同的地方,请注意区别。

3 常量与转义符

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重新计算。

5 数组

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

6 操作符

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

操 作
符 号
说 明
赋值
= += -= *= /= %= ^=
^=是特别的操作符,C没有
 条件
?:
 
 逻辑或
||
 
  逻辑与
&&
 
数组元素
 in
 if (i in a )
匹配
~  !~
C没有
关系
< <= == != >= >
 
字符串连接
(blank)
“a” “ab” (=”abc”)
加减
+ -
 
乘除求模
* / %
 
单目加减
+ -
-x 正负
逻辑非

!$1
开方
^   (**)
有些现代版本的awk可以用**
自加、自减
++  --
++x  x++
字段运算符
$
$i 第i字段
括号
()
 
 

7 流程控制

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值为返回值)

8 函数

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 输入输出

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  awk linux