shell学习之awk小记

 awk中并没有提供类似C语言fopen或者fprintf函数,但是awk的任何输出函数皆可以由Unix的I/O Redirection,将输出的资料重定位到指定文件,其符号为>或者>>。

建立档案如下:

tmp文件:

 1  1034         7:26
2 1025 7:27
3 1101 7:32
4 1006 7:45
5 1012 7:46
6 1028 7:49
7 1051 7:51
8 1029 7:57
9 1042 7:59
10 1008 8:01
11 1052 8:05
12 1005 8:12

awk文件:

1 BEGIN {print "ID NUMBER ARRIVAL TIME" > "test"
2 print "=========================" > "test"}
3 {printf(" %s %s\n", $1, $2) > "test"}

在awk文件中,输出文件名test被双括号(“”)括住,表示test为字符串常量,否则,test将被解释为awk变量。

另外,重定向的时候使用>而非>>,awk第一次执行该指令时把资料append到test末尾,并不是每执行一次就打开一次新文档,这与UNIX不同。在awk中,使用操作符>,会首先清空打开的文件,文件一旦被打开,就会一直保持打开状态,除非显示的关闭或者awk程序终止。

 

awk如何使用系统资源

 awk很容易使用系统资源。包括在awk表达式中使用shell命令来处理部分数据,或者使用shell命令将产生的结果交回awk,这个过程是由awk提供的pipe(虽然有些类似Unix的pipe,但特性有些不同),以及一个从awk中调用UNIX的shell command语法构成的。

注意:

1、awk提供的pipe类似UNIX,其记号为“|”,用法含义如下:

a、awk output指令 | “shell接受的指令”

如:print $1,$2 | "sort "

b、“shell接受的指令 |  awk input指令

如:"ls "   |  getline

其中,awk的input指令只有一个getline, output指令有两个print和printf。

2、awk提供另外一种调用shell命令的方法,system("shell命令")。

如:

awk 'BEGIN{system("date > data.dat") getline}' 

 

 在awk中可以定义自己的函数,function为保留字,awk提供的close()指令,语法有两种,

close(filename);

close(置于pipe之前的command):例如:close("sort"),意思是为close命令中置于sort之前的pipe,并立刻调用shell来执行sort,若未执行这指令,awk必须于结束整个命令后从才执行上述动作。

reformat.awk文件如下:

  1 #!/usr/bin/awk -f
2
3 BEGIN {
4 FS="[ \t:]+"
5 "date"|getline
6 print "Today is " $2 $3 > "today_rpt"
7 print "====================" > "today_rpt"
8 print "ID Number Arrival Time" > "today_rpt"
9 close("today_rpt")
10 }
11 {
12 arrival = HM_to_M($2,$3)
13 printf " %s %s:%s %s\n", $1,$2,$3,(arrival > 480 ? "*" : " ") | "sort >> today_rpt"
14 total+=arrival
15 }
16 END{
17 close("today_rpt")
18 close("sort >> today_rpt")
19 printf "Average arrival time : %d:%d\n", total/NR/60, (total/NR)%60 >> "today_rpt"
20 }
21 function HM_to_M(hour, min) {
22 return hour*60 + min
23 }

执行

1 $ chmod 777 reformat3 
2 $ ./reformat3 tmp

在这个程序文件中,定义了函数function,注意close关闭命令。close("sort >> today_rpt")的意思是对在pipe之前的command,立即执行sort命令,否则,sort之后的资料将会出现在Average arrival time之后,也就是说awk调用shell命令的输出结果,并没有立即写道文件中,而是当命令关闭(或者整个程序结束)时才写进去。由于shell排序之后的数据也要写到today_rpt文件中,为了防止两个进程同时写,在sort之前必须关闭文件。


在AWK中,处理函数参数列表中的参数外,所有变量都是全局变量,对于递归函数内部的参数,会因为它呼叫子函数(本身)而重复使用。

  1 #!/usr/bin/awk -f
2
3 BEGIN {
4 x = 35
5 y = 45
6 test_variable(x)
7 printf "Return to main : arg1=%d, x=%d, y=%d, z=%d\n", arg1, x, y, z
8 }
9
10 function test_variable(arg1) {
11 arg1++
12 y++
13 z=55
14 printf "Inside the function : arg1=%d, x=%d, y=%d, z=%d\n", arg1, x, y, z
15 }

函数内可任意使用主函数里面的参数,即可以改变它的值。

函数执行过程中,可以使用虚列(在函数的参数列表中声明)来记录不想被破坏的资料,这样执行子函数就不会破坏这些资料。此外,AWK并不检查调用函数传入的参数是否一致。

例如:

定义递归函数,function demo

function demo ( arg1 ) {

...

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

demo(x)

}

i为全局变量,所以执行完子函数之后,原函数的i被破坏,所以本函数无法正确执行。


AWK的匹配模式的另一种用法(没见过,直接粘贴)

Pattern1 , Pattern2

遇到這種 Pattern, AWK 會幫您設立一個 switch(或flag). 當AWK讀入的資料列使得 Pattern1 成立時, AWK 會打開(turn on) 這 switch.

當AWK讀入的資料列使得 Pattern2 成立時, AWK 會關上(turn off) 這個 switch.

該 Pattern 成立的條件是 : 當這個 switch 被打開(turn on)時 (包括 Pattern1, 或 Pattern2 成立 的情況)例 如 : FNR>= 23 && FNR< =28 { print " " $0 } 可改寫為 FNR == 23 , FNR == 28 { print " " $0 } 說 明 :

  1. 當 FNR >= 23 時, AWK 就 turn on 這個 switch;
  2. 因為隨著資料列的讀入, AWK不停的累加 FNR.
  3. 當 FNR = 28 時, Pattern2 FNR == 28 便成立, 這時 AWK 會關上這個 switch.當 switch 打開的期間, AWK 會執行 ``print " " $0''
 

 

posted @ 2012-03-02 19:17  leealways87  阅读(708)  评论(0编辑  收藏  举报