Chinaunix首页 | 论坛 | 博客
  • 博客访问: 152620
  • 博文数量: 19
  • 博客积分: 1425
  • 博客等级: 上尉
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-20 16:48
文章分类

全部博文(19)

文章存档

2009年(1)

2008年(18)

我的朋友

分类: LINUX

2008-08-28 09:29:12

a w k是一种程序语言,对文档资料的处理具有很强的功能。awk 名称是由它三个最初设计
者的姓氏的第一个字母而命名的: Alfred V. AhoPeter J. We i n b e rg e rBrian W. Kernighan
a w k
最初在1 9 7 7年完成。1 9 8 5年发表了一个新版本的a w k,它的功能比旧版本增强了不少。a w k
能够用很短的程序对文档里的资料做修改、比较、提取、打印等处理。如果使用C P a s c a l
等语言编写程序完成上述的任务会十分不方便而且很花费时间,所写的程序也会很大。
a w k
不仅仅是一个编程语言,它还是L i n u x系统管理员和程序员的一个不可缺少的工具。
a w k
语言本身十分好学,易于掌握,并且特别的灵活。
gawk
G N U计划下所做的a w kgawk 最初在1 9 8 6年完成,之后不断地被改进、更新。
gawk
包含awk 的所有功能。

6.1 gawk
的主要功能
gawk
的主要功能是针对文件的每一行( l i n e ),也就是每一条记录,搜寻指定的格式。当某
一行符合指定的格式时,gawk 就会在此行执行被指定的动作。gawk 依此方式自动处理输入文
件的每一行直到输入文件档案结束。
g a w k
经常用在如下的几个方面:
根据要求选择文件的某几行,几列或部分字段以供显示输出。
分析文档中的某一个字出现的频率、位置等。
根据某一个文档的信息准备格式化输出。
以一个功能十分强大的方式过滤输出文档。
根据文档中的数值进行计算。

6.2
如何执行gawk程序
基本上有两种方法可以执行g a w k程序。
如果gawk 程序很短,则可以将gawk 直接写在命令行,如下所示:
gawk 'program' input-file1 input-file2 ...
其中program 包括一些pattern a c t i o n
如果gawk 程序较长,较为方便的做法是将gawk 程序存在一个文件中,
gawk
的格式如下所示:
gawk -f program-file input-file1 input-file2 ...
gawk
程序的文件不止一个时,执行gawk 的格式如下所示:
gawk -f program-file1 -f program-file2 ... input-file1 input-file2 ...

6.3
文件、记录和字段
一般情况下,g a w k可以处理文件中的数值数据,但也可以处理字符串信息。如果数据没有
存储在文件中,可以通过管道命令和其他的重定向方法给g a w k提供输入。当然, g a w k只能处
理文本文件(A S C I I码文件)。

电话号码本就是一个g a w k可以处理的文件的简单例子。电话号码本由很多条目组成,每一
个条目都有同样的格式:姓、名、地址、电话号码。每一个条目都是按字母顺序排列。
g a w k中,每一个这样的条目叫做一个记录。它是一个完整的数据的集合。例如,电话号
码本中的Smith John这个条目,包括他的地址和电话号码,就是一条记录。
记录中的每一项叫做一个字段。在g a w k中,字段是最基本的单位。多个记录的集合组成了
一个文件。
大多数情况下,字段之间由一个特殊的字符分开,像空格、TA B、分号等。这些字符叫做
字段分隔符。请看下面这个/ e t c / p a s s w d文件:
t p a r k e r ; t 3 6 s 6 2 h s h ; 5 0 1 ; 1 0 1 ; Tim Parker;/home/tparker;/bin/bash
etreijs;2ys639dj3h;502;101;Ed Tr e i j s ; / h o m e / e t r e i j s ; / b i n / t c s h
y c h o w ; 1 h 2 7 s j ; 5 0 3 ; 1 0 1 ; Yvonne Chow;/home/ychow;/bin/bash
你可以看出/ e t c / p a s s w d文件使用分号作为字段分隔符。/ e t c / p a s s w d文件中的每一行都包括
七个字段:用户名;口令;用户I D;工作组I D;注释; h o m e目录;启始的外壳。如果你想要
查找第六个字段,只需数过五个分号即可。
但考虑到以下电话号码本的例子,你就会发现一些问题:
Smith John 13 Wilson St. 555-1283
Smith John 2736 Artside Dr Apt 123 555-2736
Smith John 125 Westmount Cr 555-1726
虽然我们能够分辨出每个记录包括四个字段,但g a w k却无能为力。电话号码本使用空格作
为分隔符,所以g a w k认为S m i t h是第一个字段, John 是第二个字段,1 3是第三个字段,依次类
推。就g a w k而言,如果用空格作为字段分隔符的话,则第一个记录有六个字段,而第二个记
录有八个字段。
所以,我们必须找出一个更好的字段分隔符。例如,像下面一样使用斜杠作为字段分隔
符:
Smith/John/13 Wilson St./555-1283
Smith/John/2736 Artside Dr/Apt/123/555-2736
Smith/John/125 Westmount Cr/555-1726
如果你没有指定其他的字符作为字段分隔符,那么g a w k将缺省地使用空格或TA B作为字段
分隔符。

6.4
模式和动作
g a w k语言中每一个命令都由两部分组成:一个模式( p a t t e r n)和一个相应的动作
a c t i o n)。只要模式符合,g a w k就会执行相应的动作。其中模式部分用两个斜杠括起来,而动
作部分用一对花括号括起来。例如:
/ p a t t e r n 1 / { a c t i o n 1 }
/ p a t t e r n 2 / { a c t i o n 2 }
/ p a t t e r n 3 / { a c t i o n 3 }
所有的g a w k程序都是由这样的一对对的模式和动作组成的。其中模式或动作都能够被省
略,但是两个不能同时被省略。如果模式被省略,则对于作为输入的文件里面的每一行,动作
都会被执行。如果动作被省略,则缺省的动作被执行,既显示出所有符合模式的输入行而不做
任何的改动。
下面是一个简单的例子,因为gawk 程序很短,所以将gawk 程序直接写在外壳命令行:
gawk '/tparker/' /etc/passwd
此程序在上面提到的/ e t c / p a s s w d文件中寻找符合t p a r k e r模式的记录并显示(此例中没有动
作,所以缺省的动作被执行)。
让我们再看一个例子:
gawk '/UNIX/{print }' file2.data
此命令将逐行查找f i l e 2 . d a t a文件中包含U N I X的记录,并打印这些记录的第二个字段。
你也可以在一个命令中使用多个模式和动作对,例如:
gawk '/scandal/{print } /rumor/{print }' gossip_file
此命令搜索文件g o s s i p _ f i l e中包括s c a n d a l的记录,并打印第一个字段。然后再从头搜索
g o s s i p _ f i l e
中包括r u m o r的记录,并打印第二个字段。

6.5
比较运算和数值运算
g a w k
有很多比较运算符,下面列出重要的几个:
= =
相等
! =
不相等
>
大于
<
小于
> =
大于等于
< =
小于等于
例如:
gawk ' > 100' testfile
将会显示文件testfile 中那些第四个字段大于1 0 0的记录。
下表列出了g a w k中基本的数值运算符。
运算符说明示例
+
加法运算2+6
-
减法运算6-3
*
乘法运算2*5
/
除法运算8/4
^
乘方运算3^2 (=9)
%
求余数9%4 (=1)
例如:
{print /2}
显示第三个字段被2除的结果。
g a w k中,运算符的优先权和一般的数学运算的优先权一样。例如:
{print +*}
显示第二个字段和第三个字段相乘,然后和第一个字段相加的结果。
你也可以用括号改变优先次序。例如:
{print (+)*}
显示第一个字段和第二个字段相加,然后和第三个字段相乘的结果。

6.6
内部函数

g a w k
中有各种的内部函数,现在介绍如下:

6.6.1
随机数和数学函数
sqrt(x)
x 的平方根
sin(x)
x 的正弦函数
cos(x)
x 的余弦函数
a t a n 2 ( x
y) x / y的余切函数
log(x)
x 的自然对数
exp(x)
x e 次方
int(x)
x 的整数部分
rand()
0 1之间的随机数
srand(x)
x 设置为r a n d ( )的种子数

6.6.2
字符串的内部函数
• i n d e x ( i n
find) 在字符串in 中寻找字符串find 第一次出现的地方,返回值是字符串
find
出现在字符串in 里面的位置。如果在字符串in 里面找不到字符串f i n d,则返回值为
0

例如:
print index("peanut"
" a n " )
显示结果3
• length(string)
求出string 有几个字符。
例如:
l e n g t h ( " a b c d e " )
显示结果5
• m a t c h ( s t r i n g
r e g e x p ) 在字符串string 中寻找符合regexp 的最长、最靠左边的子字
符串。返回值是regexp string 的开始位置,即i n d e x值。match 函数将会设置系统变量
R S TA RT
等于i n d e x的值,系统变量RLENGTH 等于符合的字符个数。如果不符合,则会
设置R S TA RT 0RLENGTH - 1
• s p r i n t f ( f o r m a t
e x p r e s s i o n 1. . . ) printf 类似,但是sprintf 并不显示,而是返回字符
串。
例如:
sprintf("pi = %.2f (approx.)"
2 2 / 7 )
返回的字符串为pi = 3.14 (approx.)
• s u b ( r e g e x p
r e p l a c e m e n tt a rg e t ) 在字符串t a rget 中寻找符合regexp 的最长、最靠左的
地方,以字串replacement 代替最左边的r e g e x p
例如:
str = "water
w a t e re v e r y w h e r e "
s u b ( / a t /
" i t h "s t r )
结果字符串s t r会变成
w i t h e r
w a t e re v e r y w h e r e
• g s u b ( r e g e x p
r e p l a c e m e n tt a rget) 与前面的s u b类似。在字符串t a rget 中寻找符合
r e g e x p
的所有地方,以字符串replacement 代替所有的r e g e x p
例如:
s t r = " w a t e r
w a t e re v e r y w h e r e "g s u b ( / a t / " i t h "s t r )
结果字符串s t r会变成
w i t h e r
w i t h e re v e r y w h e r e
• s u b s t r ( s t r i n g
s t a r tlength) 返回字符串string 的子字符串,这个子字符串的长度为
l e n g t h
,从第start 个位置开始。
例如:
s u b s t r ( " w a s h i n g t o n "
53 )
返回值为i n g
如果没有length ,则返回的子字符串是从第start 个位置开始至结束。
例如:
s u b s t r ( " w a s h i n g t o n "
5 )
返回值为i n g t o n
• tolower(string)
将字符串s t r i n g的大写字母改为小写字母。
例如:
tolower("MiXeD cAsE 123")
返回值为mixed case 123
• toupper(string)
将字符串s t r i n g的小写字母改为大写字母。
例如:
toupper("MiXeD cAsE 123")
返回值为MIXED CASE 123

6.6.3
输入输出的内部函数
• close(filename)
将输入或输出的文件filename 关闭。
• system(command)
此函数允许用户执行操作系统的指令,执行完毕后将回到g a w k
序。
例如:
BEGIN

6.7
字符串和数字
字符串就是一连串的字符,它可以被g a w k逐字地翻译。字符串用双引号括起来。数字不能
用双引号括起来,并且g a w k将它当作一个数值。例如:
gawk ' != "Tim" ' testfile
此命令将显示第一个字段和Ti m不相同的所有记录。如果命令中Ti m两边不用双引号,
g a w k
将不能正确执行。
再如:
gawk ' == "50" ' testfile
此命令将显示所有第一个字段和5 0这个字符串相同的记录。g a w k不管第一字段中的数值
的大小,而只是逐字地比较。这时,字符串5 0和数值5 0并不相等。

6.8
格式化输出
我们可以让动作显示一些比较复杂的结果。例如:
gawk ' != "Tim" {print
$ 5$ 6}' testfile
将显示t e s t f i l e文件中所有第一个字段和Ti m不相同的记录的第一、第五、第六和第二个字
段。
进一步,你可以在p r i n t动作中加入字符串,例如:
gawk ' != "Tim" {print "The entry for "
$ 1"is not Tim. "}' testfile
p r i n t
动作的每一部分用逗号隔开。
借用C语言的格式化输出指令,可以让g a w k的输出形式更为多样。这时,应该用p r i n t f而不
p r i n t。例如:
{printf "%5s likes this language\n"
$ 2 }
p r i n t f
中的%5s 部分告诉gawk 如何格式化输出字符串,也就是输出5个字符长。它的值由
printf
的最后部分指出,在此是第二个字段。\ n是回车换行符。如果第二个字段中存储的是人
名,则输出结果大致如下:
Tim likes this language
G e o ff likes this language
Mike likes this language
Joe likes this language
gawk
语言支持的其他格式控制符号如下:
• c
如果是字符串,则显示第一个字符;如果是整数,则将数字以ASCII 字符的形式显示。
例如:
printf “% c”
6 5
结果将显示字母A
• d
显示十进制的整数。
• i
显示十进制的整数。
• e
将浮点数以科学记数法的形式显示。
例如:
print “$ 4 . 3 e”
1 9 5 0
结果将显示1 . 9 5 0 e + 0 3
• f
将数字以浮点的形式显示。
• g
将数字以科学记数法的形式或浮点的形式显示。数字的绝对值如果大于等于0 . 0 0 0 1
以浮点的形式显示,否则以科学记数法的形式显示。
• o
显示无符号的八进制整数。
• s
显示一个字符串。
• x
显示无符号的十六进制整数。1 01 5af表示。
• X
显示无符号的十六进制整数。1 01 5AF表示。
• %
它并不是真正的格式控制字符,% %将显示%
当你使用这些格式控制字符时,你可以在控制字符前给出数字,以表示你将用的几位或几
个字符。例如,6 d表示一个整数有6位。再请看下面的例子:
{printf "%5s works for %5s and earns %2d an hour"
$ 1$ 2$ 3 }
将会产生类似如下的输出:
Joe works for Mike and earns 12 an hour
当处理数据时,你可以指定数据的精确位数
{printf "%5s earns $%.2f an hour"
$ 3$ 6 }
其输出将类似于:
Joe earns .17 an hour
你也可以使用一些换码控制符格式化整行的输出。之所以叫做换码控制符,是因为g a w k
这些符号有特殊的解释。下面列出常用的换码控制符:
\a
警告或响铃字符。
\b
后退一格。
\f
换页。
\n
换行。
\r
回车。
\t Ta b

\v
垂直的t a b



1.awk的常规表达式元字符
\
换码序列
^
在字符串的开头开始匹配
$
在字符串的结尾开始匹配
.
与任何单个字符串匹配
[ABC]
[]内的任一字符匹配
[A-Ca-c]
A-Ca-c范围内的字符匹配(按字母表顺序)
[^ABC]
与除[]内的所有字符以外的任一字符匹配
Desk|Chair
DeskChair中的任一个匹配
[ABC][DEF]
关联。与ABC中的任一字符匹配,且其后要跟DEF中的任一个字符。
*
ABC中任一个出现0次或多次的字符相匹配
+
ABC中任何一个出现1次或多次的字符相匹配
与一个空串或ABC在任何一个字符相匹配
Blue|Blackberry 合并常规表达式,与BlueberryBlackberry相匹配

2.awk
算术运算符
运算符用途
------------------
x^y x
y次幂
x**y
同上
x%y
计算x/y的余数(求模)
x+y x
y
x-y x
y
x*y x
y
x/y x
y
-y
y(y的开关符号);也称一目减
++y y
1后使用y(前置加)
y++
使用y值后加1(后缀加)
--y y
1后使用y(前置减)
y--
使用后y1(后缀减)
x=y
y的值赋给x
x+=y
x+y的值赋给x
x-=y
x-y的值赋给x
x*=y
x*y的值赋给x
x/=y
x/y的值赋给x x%=y x%y的值赋给x
x^=y
x^y的值赋给x
x**=y
x**y的值赋给x

3.awk
允许的测试:
操作符 含义
x==y x
等于y
x!=y x
不等于y
x>y x
大于y
x>=y x
大于或等于y
x<=y x
小于或等于y
x~re x
匹配正则表达式re
x!~re x
不匹配正则表达式re

4.awk
的操作符(按优先级升序排列)
=
+= -= *= /= %=
||
&&
>; >;= < <= == != ~ !~
xy (
字符串连结,’x’’y’变成"xy"
+ -
* / %
++ --

5.awk
内置变量(预定义变量)
说明:表中v项表示第一个支持变量的工具(下同):A=awkN=nawk,P=POSIX awk,G=gawk
V
变量 含义 缺省值
--------------------------------------------------------
N ARGC
命令行参数个数
G ARGIND
当前被处理文件的ARGV标志符
N ARGV
命令行参数数组
G CONVFMT
数字转换格式 %.6g
P ENVIRON UNIX
环境变量
N ERRNO UNIX
系统错误消息
G FIELDWIDTHS
输入字段宽度的空白分隔字符串
A FILENAME
当前输入文件的名字
P FNR
当前记录数
A FS
输入字段分隔符 空格
G IGNORECASE
控制大小写敏感0(大小写敏感)
A NF
当前记录中的字段个数
A NR
已经读出的记录数
A OFMT
数字的输出格式 %.6g
A OFS
输出字段分隔符 空格
A ORS
输出的记录分隔符 新行
A RS
输入的记录他隔符 新行
N RSTART
被匹配函数匹配的字符串首
N RLENGTH
被匹配函数匹配的字符串长度
N SUBSEP
下标分隔符 "\034"

6.awk
的内置函数
V
函数 用途或返回值
------------------------------------------------
N gsub(reg,string,target)
每次常规表达式reg匹配时替换target中的string
N index(search,string)
返回stringsearch串的位置
A length(string)
求串string中的字符个数
N match(string,reg)
返回常规表达式reg匹配的string中的位置
N printf(format,variable)
格式化输出,按format提供的格式输出变量variable
N split(string,store,delim)
根据分界符delim,分解stringstore的数组元素
N sprintf(format,variable)
返回一个包含基于format的格式化数据,variables是要放到串中的数据
G strftime(format,timestamp)
返回一个基于format的日期或者时间串,timestmpsystime()函数返回的时间
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()
返回自197011日以来经过的时间(按秒计算)

 


其它参考资料:

http://www-128.ibm.com/developerworks/cn/linux/shell/awk/awk-1/index.html

http://www-128.ibm.com/developerworks/cn/linux/shell/sed/sed-1/index.html

阅读(1504) | 评论(0) | 转发(0) |
0

上一篇:dd命令使用

下一篇:vi命令及删除命令精典

给主人留下些什么吧!~~