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 } 說 明 :
- 當 FNR >= 23 時, AWK 就 turn on 這個 switch;
- 因為隨著資料列的讀入, AWK不停的累加 FNR.
- 當 FNR = 28 時, Pattern2 FNR == 28 便成立, 這時 AWK 會關上這個 switch.當 switch 打開的期間, AWK 會執行 ``print " " $0''