全部博文(368)
分类: LINUX
2010-04-23 15:16:39
CODE:
- 左对齐
Wi d t h 域的步长,用0表示0步长
. p r e c 最大字符串长度,或小数点右边的位数
表9-7 awk printf格式
% c A S C I I字符
% d 整
数
% e 浮
点数,科学记数法
% f 浮
点数,例如(1
2 3 . 4 4)
% g a w k决定使用哪种浮点数转换e或者f
% o 八
进制数
% s 字
符串
% x 十
六进制数
1. 字符转换
观察A S C I I码中6 5的等价值。管道输出6 5到a w k。p r i n t f进行A S C I I码字符转换。这里也加入换行,因为缺省情况下p
r i n t f不做换行动作。
CODE:
A[sam@chenwy
sam]$
echo "65" | awk '{printf "%c\n",$0}'
A
按同样
方式使用a w k得到同样结果。
CODE:
[sam@chenwy
sam]$ awk
'BEGIN{printf "%c\n",65}'
A
所有的
字符转换都是一样的,下面的例子表示进行浮点数转换后‘
9 9
CODE:
[sam@chenwy
sam]$ awk
'BEGIN{printf "%f\n",999}'
999.000000
2. 格式化输出
打印所
有的学生名字和序列号,要求名字左对齐,
1 5个
字符长度,后跟序列号。注意\ n换行符放在最后一个指示符后面。输出将自动分成两列。
CODE:
[root@chenwy
sam]#
awk '{printf "%-15s %s\n",$1,$3}' grade.txt
M.Tans 48311
J.Lulu 48317
P.Bunny 48
J.Troll
加入一
些文本注释帮助理解报文含义。可在正文前嵌入头信息。注意这里使用p r i n t加入头信息。如果愿意,也可使用p r i n t f。
CODE:
[root@chenwy
sam]#
awk 'BEGIN{print "Name\t\tS.Number"}{printf "%-15s
%s\n",$1,$3}' grade.txt
Name S.Number
M.Tans 48311
J.Lulu 48317
P.Bunny 48
J.Troll
3.向一行a
w k命令传值
在查看a w k脚本前,先来查看怎样在a w k命令行中传递变量。
在a w k执行前将值传入a w k变量,需要将变量放在命令行中,格式如下:
CODE:
awk 命令变量=输入文件值
(后面
会讲到怎样传递变量到a w k脚本中)。
下面的
例子在命令行中设置变量A G E等于1 0,然后传入a w k中,查询年龄在1 0岁以下的所有学生。
CODE:
[root@chenwy
sam]#
awk '{if ($5
J.Lulu 06/99 48317 green 9 24 26
要快速
查看文件系统空间容量,观察其是否达到一定水平,可使用下面a w k一行脚本。因为要监视的已使用空间
容量不断在变化,可以在命令行指定一个触发值。首先用管道命令将df -k 传入a w k,然后抽出第4列,即剩余可利用空间容量。使用$ 4 ~ / ^ [ 0 - 9 ] /取得容量数值(1 0 2 4块)而不是d f的文件头,然后对命令行与‘ i f ( $ 4
< T R I G G E R )’上变量T R I G G E R中指定
的值进
行查询测试。
CODE:
[root@chenwy
sam]# df
-k|awk '{if($4
/dev/shm 99352
CODE:
[root@chenwy
sam]# df
-k|awk '($4~/^[0-9]/) {if($4
/boot 458589
/dev/shm 99352
($4~/^[0-9]/)好像没什么用
在系统
中使用df -k命令,产生下列信息:
CODE:
[root@chenwy
sam]# df
-k
文件系
统
1K-块 已用
可
用 已用% 挂载点
/dev/sda2 5162828
2289804 2610764 47% /
/dev/sda1
497829 13538 458589 3%
/boot
none
99352 0
99352 0% /dev/shm
如果系
统中d f输出格式不同,必须相应改变列号以适应工作系统。
当然可
以使用管道将值传入a w k。本例使用w h o命令, w h o命令第一列包含注册用户名,这里打印注册用户,并加入一定信息。
CODE:
[sam@chenwy
sam]$ who
|awk '{print $1" is logged on"}'
root is logged on
root is logged on
[sam@chenwy sam]$ who
root :0
Nov 23 20:17
root pts/0 Nov 23
20:25 (:0.0)
a w k也允许传入环境变量。下面的例子使用环境变量HOME支持当前用户目录。可从pwd命令管道输出到a w k中获得相应信息。
CODE:
[sam@chenwy
sam]$ pwd
| awk '{if ($1==derr) print $1}' derr=$HOME
/usr/sam
4. awk脚本文件
可以将a w k脚本写入一个文件再执行它。命令不必很长(尽管这是写入一个脚本文件的主要原因),甚至可以接受一行命令。这样可以保存a w k命令,以使不必每次使用时都需要重新输入。使用文件的另一个好处是可以增加注释,以便于理解脚本的真正用途和功能。
使用前
面的几个例子,将之转换成a w k可执行文件。像原来做的一样,将学生目前级别分相加awk
‘(t
o t + = $ 6)
END{print "club student total points:" t o t }’ g r a d e .
t x t。
创建新
文件s t u d e n t _ t o t
. a w k,给所有a
w k程
序加入a
w k扩
展名是一种好习惯,这样通过查看文件名就知道这是一个a w k程序。文本如下:
CODE:
[sam@chenwy
sam]$ cat
student_tot.awk
#!/bin/awk -f
#all commnet lines must start with a hash '#'
#name:students_tots.awk
#to call:student_tot.awk grade.txt
#prints total and average of club student points
#print a header first
BEGIN{
print
"Student Date Member No. Grade
Age Points Max"
print "Name Joined
Gained Point Available"
print
"=============================================================="
}
#let's add the scores of points gained
(tot+=$6)
#finished proessing now let's print the total and average point
END{
print "Club student total points :" tot
print "Average Club Student Points:" tot/NR}
通过将
命令分开,脚本可读性提高,还可以在命令之间加入注释。这里加入头
信息和
结尾的平均值。基本上这是一个一行脚本文件。
执行
时,在脚本文件后键入输入文件名,但是首先要对脚本文件加入可执行权限。
CODE:
[sam@chenwy
sam]$
chmod u+x student_tot.awk
[sam@chenwy sam]$./student_tot.awk grade.txt
Student Date Member No. Grade
Age Points Max
Name Joined
Gained Point Available
==============================================================
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26
Club student total points :155
Average Club Student Points:31
过
滤相同行:
如有一
个文件strip中有多条重复错误提法:
CODE:
[sam@Linux_chenwy
sam]$
cat strip
etreiytrpytyu
ERROR*
ERROR*
ERROR*
ERROR*
IUEWROPYJRTMELUYK
ERROR*
ERROR*
ERROR*
ERROR*
ERROR*
ERROR*
EWUTIRWJYHT
ERROR*
ERROR*
JGIOERYO56ERU
ERROR*
ERROR*
ERROR*
JGEORYKP65EKU;YK,
现在用a w k脚本过滤出错误行的出现频率,使得每一个失败记录只对应一个错误行。awk脚本如下:
CODE:
[sam@Linux_chenwy
sam]$
cat error_strip.awk
#!/bin/awk -f
#error_strip.awk
#to call:error_strip.awk
#strips out the ERROR* lines if there are more than one
#ERROR* lines after each failed record.
BEGIN {error_line=""}
#tell awk the whole is "ERROR*"
{if ($0=="ERROR*" && error_line=="ERROR*")
#go to next line
next;
error_line=$0;print}
执行结
果如下:
CODE:
[sam@Linux_chenwy
sam]$
./error_strip.awk strip
etreiytrpytyu
ERROR*
IUEWROPYJRTMELUYK
ERROR*
EWUTIRWJYHT
ERROR*
JGIOERYO56ERU
ERROR*
JGEORYKP65EKU;YK,
5.
在a
w k中使用F
S变量
如果使
用非空格符做域分隔符( F S)浏览文件,例如# 或:,编写这样的一行命令很容易,
因为使用F
S选项
可以在命令行中指定域分隔符。
CODE:
$awk -F: '{print
$0}'
inputfile
使用a w k脚本时,记住设置F S变量是在B E G I N部分。如果不这样做, a w k将会发生混淆,不知道域分隔符是什么。
下述脚
本指定F S变量。脚本从/ e t c / p a s s
w d文
件中抽取第1和第5域,通过分号“;”分隔p a s s w d文件域。第1域是帐号名,第5域是帐号所有者。
我
举的例子是第七个域:
CODE:
[sam@Linux_chenwy
sam]$
awk -F: '{print $1,"\t",$7}' passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
.................................
这是不
用脚本的,后面的结果省略
现使用
脚本如下:
CODE:
[sam@Linux_chenwy
sam]$
cat passwd.awk
#!/bin/awk -f
#to call:passwd.awk /etc/passwd
#print out the first and seventh fields
BEGIN{
FS=":"}
{print $1,"\t",$7}
结果如
下:
CODE:
[sam@Linux_chenwy
sam]$
chmod u+x passwd.awk
[sam@Linux_chenwy sam]$ ./passwd.awk passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
.......................................
6. 向a
w k脚本传值
向a w k脚本传值与向a w k一行命令传值方式大体相同,格式为:
CODE:
awk script_file
var=value input_file
下述脚
本对比检查文件中域号和指定数字。这里使用了N
F变量M
A X,
表示指定检查的域号,使用双引号将域分隔符括起来,即使它是一个空格。
脚本如
下:
CODE:
[sam@Linux_chenwy
sam]$
cat fieldcheck.awk
#!/bin/awk -f
#check on how many fields in a file
#name:fieldcheck.awk
#to call:fieldcheck MAX=n FS=
#
NF!=MAX{
print("line" NR " does not have " MAX "fields")}
如果NF中的值不等于最大MAX值,则打印出"哪一行的域总数不是max"
如果以/ e t c / p a s s w d作输入文件(p a s s w d文件有7个域),运行上述脚本。参数格式如下:
CODE:
[sam@Linux_chenwy
sam]$
chmod u+x fieldcheck.awk
[sam@Linux_chenwy sam]$ ./fieldcheck.awk MAX=7 FS=":" passwd
正好7个域,如果改成6,就会显示不同结果,试试看?
使用前
面一行脚本的例子,将之转换成a
w k脚
本如下:
CODE:
[sam@Linux_chenwy
sam]$
cat name.awk
#!/bin/awk -f
#name:age.awk
#to call:age.awk AGE=n grade.txt
#print ages that are lower than the age supplied on the comand line
{if ($5
文本包
括了比实际命令更多的信息,没关系,仔细研读文本后,就可以精确知道其功能及如何调用它。
不要忘
了增加脚本的可执行权限,然后将变量和赋值放在命令行脚本名字后、输入文件前执行。
CODE:
[sam@Linux_chenwy
sam]$
chmod u+x name.awk
[sam@Linux_chenwy sam]$ ./name.awk AGE=10 grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
同样可
以使用前面提到的管道命令传值,下述a
w k脚
本从d
u命令
获得输入,并输出块和字节数。
CODE:
[root@Linux_chenwy
sam]#
cat duawk.awk
#!/bin/awk -f
#to call:du|duawk.awk
#prints file/direc's in bytes and blocks
BEGIN{
OFS="\t";
print "name" "\t\t","bytes","blocks\n"
print "==============================="}
{print $2,"\t\t",$1*512,$1}
使用du的结果如下
CODE:
[root@Linux_chenwy
sam]#
du
12 ./.kde/Autostart
16 ./.kde
8 ./.xemacs
4 ./sam
4 ./dir1
4 ./file6
184 .
执行:
CODE:
[root@Linux_chenwy
sam]#
du | ./duawk.awk
name
bytes blocks
===============================
./.kde/Autostart
6144 12
./.kde
8192 16
./.xemacs
4096 8
./sam
2048 4
./dir1
2048 4
./file6
2048 4
.
94208
184
CODE:
OFS="\t";
是什么
意思了,好累,晚上再研究,谁解答一下更好
数
组
前面讲
述s p l i t函数时,提到怎样使用它将元素划分进一个数组。这里还有一个例子:
CODE:
[sam@Linux_chenwy
sam]$
awk 'BEGIN {print split("123#456#789",myarray,"#")}'
3
实际上m y a r r a y数组为
CODE:
Myarray[1]="123"
Myarray[2]="456"
Myarray[3]="789"
数组使
用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是一种循环类型的基本结构:
CODE:
For (element in
array
) print array[element]
对于记
录“ 1 2 3 # 4 5 6 # 6 7
CODE:
[sam@Linux_chenwy
sam]$
cat arraytest.awk
#!/bin/awk -f
#name:arraytest.awk
#prints out an array
BEGIN{
record="123#456#789";
split(record,myarray,"#")}
END{for (i in myarray) {print myarray[i]}}
要运行
脚本,使用/ d e v / n u l l作为输入文件。
CODE:
sam@Linux_chenwy
sam]$chmod u+x arraytest.awk
[sam@Linux_chenwy sam]$ ./arraytest.awk /dev/null
123
456
789
[sam@Linux_chenwy sam]$
数
组和记录
上面的
例子讲述怎样通过s p l i t函数使用数组。也可以预先定义数组,并使用它与域进行比较测试,下面的例
子中将使用更多的数组。
下面是
从空手道数据库卸载的一部分数据,包含了学生级别及是否是成人或未成年人的信息,有两个域,分隔符为( #),文件如下:
CODE:
[sam@Linux_chenwy
sam]$
cat grade_student.txt
Yellow#Junior
Orange#Senior
Yellor#Junior
Purple#Junior
Brown-2#Junior
White#Senior
Orange#Senior
Red#Junior
Red#Junior
Brown-2#Senior
Yellow#Senior
Red#Junior
Blue#Senior
Green#Senior
Purple#Junior
White#Junior
脚本功
能是读文件并输出下列信息。
1) 俱
乐部中Ye
l l o w、O
r a n g e和R
e d级
别的人各是多少。
2 ) 俱
乐部中有多少成年人和未成年人。
查看文
件,也许2 0秒内就会猜出答案,但是如果记录超过6
0个又
怎么办呢?这不会很容易就看出来,必须使用a w k脚本。
首先看
看a w k脚本,然后做进一步讲解。
CODE:
[sam@Linux_chenwy
sam]$
cat belts.awk
#!/bin/awk -f
#name:belts.awk
#to call:belts.awk grade2.txt
#loops through the grade2.txt file and counts how many
#belts we have in (yellow,orange,red)
#also count how many adults and juniors we have
#
#start of BEGIN
#set FS and load the arrays with our values
#B E G I N部分设置F
S为符
号#,即域分隔符
BEGIN{FS="#"
#Load the belt colours we are interested in only
#因为
要查找Ye
l l o w、O
r a n g e和R
e d三
个级别。
#然后
在脚本中手工建立数组下标对学生做同样的操作。
#注
意,脚本到此只有下标或元素,并没有给数组名本身加任何注释。
belt["Yellow"]
belt["Orange"]
belt["Red"]
#end of BEGIN
#load the student type
student["Junior"]
student["Senior"]
}
##初
始化完成后,
B E G I N部分结束。记住B
E G I N部分并没有文件处理操作。
#loop thru array that holds the belt colours against field-1
#if we have a match,keep a running total
#现在
可以处理文件了。
#首先
给数组命名为c
o l o r,使用循环语句测试域1级别列是否
#等于
数组元素之一(Ye
l l o w、O
r a n g e或R
e d),
#如果
匹配,依照匹配元素将运行总数保存进数组。
{for (colour in belt)
{if($1==colour)
belt[colour]++}}
#loop thru array that holds the student type against
#field-2 if we have a match,keep a runing total
#同样
处理数组‘
S e n i o r _ o r _ j u n i o r’,
#浏览
域2时匹配操作满足,运行总数存入j u n i o r或s e n i o r的匹配数组元素。
{for (senior_or_junior in student)
{if ($2==senior_or_junior)
student[senior_or_junior]++}}
#finished processing so print out the matches..for each array
#E N D部分打印浏览结果,对每一个数组使用循环语句并打印它。
END{for (colour in belt )print "The club has
",belt[colour],colour,"Belts"
#注意
在打印语句末尾有一个\符号,用来通知a
w k(或
相关脚本)命令持续到下一行,
#当输
入一个很长的命令,并且想分行输入时可使用这种方法。
for (senior_or_junior in student) print "The club has ",\
student[senior_or_junior],senior_or_junior,"student"}
运行脚
本前记住要加入可执行权限
CODE:
[sam@Linux_chenwy
sam]$
chmod u+x belts.awk
[sam@Linux_chenwy sam]$ ./belts.awk grade_student.txt
The club has 3 Red Belts
The club has 2 Orange Belts
The club has 2 Yellow Belts
The club has 7 Senior student
The club has 9 Junior student