awk的学习和使用(一)

上一篇 / 下一篇  2009-08-11 09:29:45 / 个人分类:Linux

最近接触了linux的使用和一些命令、工具的使用,awk恐怕是linux用处最广的工具之一了,今天开始,我打算记录下我的学习过程。


一.awk的简介

与sed和grep很相似,awk是一种样式扫描与处理工具,其功能远远强于sed和grep,除了几乎所有的sed和grep功能之外,awk还可以进行样式装入,流控制,数学运算符,进程控制语句,甚至内置的变量和函数。它具备了一个完整的语言所应具备的特性,实际上awk确实拥有自己的语言,awk程序设计语言,awk的三位创建者已将其定义为:awk样式扫描和处理语言。

基于文本的样式扫描和处理是我们经常要做的工作,比如从一个上千行的具有一定格式的文本文件中找出满足要求的行并输出到一个新文本,就可以使用awk。再比如,监控网络时,由于网络上流动的数据非常多,如果需要获得某些特定的数据,使用awk过滤。简而言之,awk就是一个强大的文本处理工具。

在这里有一个可遵循的一般原则:如果你用普通的shell工具或shell script有困难的话,试试awk,如果awk仍不能解决问题,则便用C语言,如果C语言仍然失败,则移至C++。

二.awk的调用方式

1.awk命令行的方式,适用于解决简单问题,例如:打印testfile文本中第一列为abc的所有行(省略了print)

[root@test myself]# awk '$1==abc' testfile

2.使用-f选项调用awk程序文件,例如:将一段awk程序保存到文本,名为testawk1,在命令行中执行该文件

[root@test myself]# awk -f testawk1 testfile

3.利用命令解释器调用awk,例如:将一段awk程序保存至文本,名为myawk,与前面不同的是该文本首行需要添加:#!/bin/awk -f ,保存后赋予该文件执行权限,命令行中直接调用:

[root@test myself]# myawk testfile

三.awk语法

awk [ -F re] [parameter...] ['prog'] [-f progfile][in_file...]

-F re: 允许awk更改其字段分隔符。

parameter:

'prog': awk程序语句段,必须使用单引号‘’引起来,防止被shell解释。

其标准形式为'pattern{action}'。前面第二节中的第一小节举例:awk '$1==abc' testfile其中'$1==abc'就是pattern,起过滤作用,即:只有符合$1==abc的行,才执行执行{action}操作。但此例中省略了{action},此时将默认执行print操作,即打印到标准输出。

pattern和{action}二者可以省略其中之一,但是不能两者同时省略。pattern省略时表示不对任何行进行过滤。

{action}中的语句之间,使用;进行分隔,使用#进行注释。

-f progfile: 允许awk调用并执行progfile文件。progfile必须是一个符合awk语法的文本文件。

in_file: awk的输入文件。awk允许对多个输入文件进行处理,其间用,隔开,awk不会修改输入文件。如果未指定输入文件,awk将接受标准输入,并将结果显示在标准输出。awk支持输入输出重定向。

四.记录、字段和内置变量

记录和字段:在awk中,缺省情况下会将文本中的一行视为一个记录,而将一行中的某一部分视作一个字段,这与数据库中对数据的处理方式类似。比如数据库中某个数据表的第一个字段名叫做ID,第二个叫做Name,在awk中使用$1、$2表示第一个字段、第二个字段。特殊的,awk用$0来表示整个行(整条记录)。

分隔符:不同的字段之间是用称作分隔符的字符分隔开的。系统默认的分隔符是空格。awk允许在命令行中用-F re的形式来改变这个分隔符。事实上,awk用一个内置的变量FS来记忆这个分隔符。

内置变量:除了FS外,awk中有好几个这样的内置变量,如记录和记录之间(行与行之间)的分隔符使用RS表示,当前工作的记录数为NR等等。这些内置的变量可以在awk程序中引用或修改,例如,可以利用NR变量在模式匹配中指定工作范围,也可以通过修改记录分隔符RS让一个特殊字符而不是换行符作为记录的分隔符。例如,以下语句表示,显示文本文件第7行到第15行中以%分给的第1、3、7个字段值。

awk -F % 'NR==7,NR==15 {printf $1 $3 $7}' testfile

awk的其他内置变量:A=awk,N=nawk,P=POSIX awk。以下内置变量以系统中的帮助为准(不同系统下的awk可能有所出入)。

P ENVIRON UNIX环境变量
A FILENAME 当前输入文件的名字
P FNR 当前记录数
A FS 输入字段分隔符 空格 
A NF 当前记录中的字段个数
A NR 已经读出的记录数
A OFMT 数字的输出格式 %.6g
A OFS 输出字段分隔符 空格
A ORS 输出的记录分隔符 新行
A RS 输入的记录他隔符 新行

五.内置函数

例:显示文件myfile中的行号和第3字段:

$awk '{printf"%03d%s\n",NR,$1}' myfile

其中,printf即内部函数,该函数类似c++中的printf,可以对输出格式进行控制;

例:下面的示例显示了内置变量和内置函数length()的使用:

$awk 'length($0)>80 {print NR}' myfile

该命令行将显示文本myfile中所有超过80个字符的行号,在这里,用$0表示整个记录(行),同时,内置变量NR不使用标志符'$'。

例:作为一个较为实际的例子,我们假设要对UNIX中的用户进行安全性检查,方法是考察/etc下的passwd文件,检查其中的passwd字段(第二字段)是否为"*",如不为"*",则表示该用户没有设置密码,显示出这些用户名(第一字段)。我们可以用如下语句实现:

#awk -F: '$2=="" {printf("%s no password!\n",$1' /etc/passwd

在这个示例中,passwd文件的字段分隔符是“:”,因此,必须用-F:来更改默认的字段分隔符,这个示例中也涉及到了内置函数printf的使用。

其他内置函数:(以自己系统中的帮助为准)

N gsub(reg,string,target) 每次常规表达式reg匹配时替换target中的string
N index(search,string) 返回string中search串的位置
A length(string) 求串string中的字符个数
N match(string,reg) 返回常规表达式reg匹配的string中的位置
N printf(format,variable) 格式化输出,按format提供的格式输出变量variable。
N split(string,store,delim) 根据分界符delim,分解string为store的数组元素
N sprintf(format,variable) 返回一个包含基于format的格式化数据,variables是要放到串中的数据
G strftime(format,timestamp) 返回一个基于format的日期或者时间串,timestmp是systime()函数返回的时间
N sub(reg,string,target) 第一次当常规表达式reg匹配,替换target串中的字符串
A substr(string,position,len) 返回一个以position开始len个字符的子串
P totower(string) 返回string中对应的小写字符
P toupper(string) 返回string中对应的大写字符
A atan(x,y) x的余切(弧度)
N cos(x) x的余弦(弧度)
A exp(x) e的x幂
A int(x) x的整数部分
A log(x) x的自然对数值
N rand() 0-1之间的随机数
N sin(x) x的正弦(弧度)
A sqrt(x) x的平方根
A srand(x) 初始化随机数发生器。如果忽略x,则使用system()
G system() 返回自1970年1月1日以来经过的时间(按秒计算)

六.awk的自定义变量

awk允许用户在awk程序语句中定义并调用自已的变量。当然这种变量不能与内置变量及其它awk保留字相同。与C语言不同的是,awk中不需要对变量进行初始化,awk根据其在awk中第一次出现的形式和上下文确定其具体的数据类型。当变量类型不确定时,awk默认其为字符串类型。这里有一个技巧:如果你要让你的awk程序知道你所使用的变量的明确类型,你应当在在程序中给它赋初值。

举例:

awk '[name=$1;pwd=$2;print $1,$2]'  user.log

说明:上例中的name、pwd均为自定义变量,不需初始化,非常简便.


TAG:

引用 删除 slippercc   /   2010-02-24 15:58:35

总结得很好,最近正在学习这个,感谢刘童鞋。
 

评分:0

我来说两句

Open Toolbar