【细心钻研】awk我就收下了

其实也没啥,感觉和sed一点点像,不过倒是处理方式不是特别一致。

入门看的是e文的资料,一个某国同志写的

http://www.ibm.com/developerworks/linux/library/l-awk1/index.html

http://www.ibm.com/developerworks/linux/library/l-awk2/index.html

http://www.ibm.com/developerworks/linux/library/l-awk3/index.html

这三个文章基本就把事情说明白了,但是其实用的时候还是有很多东西是自己要查的,比如gensub和gsub,match variable的使用什么的还得自己去试用,唉,不过主要写了两个脚本基本的概念也就都清楚了。

首先,我的感觉awk是一种特别适合处理表格类型数据的工具,因为其本身就对分隔符非常敏感,对csv这种数据处理起来更是得心应手,会自动的用一个叫做FS(field separator)(默认为\s)的东西把每一行都分开,同时用一个NF(number field)变量来记录每行分开的次数,同时RS(record separator)(默认为\n)是一个更大规模的分隔符,像是field separator,但是范围更大,同时NR(number record)来记录次数,这里的NR采用RS默认的\n,相当于就和行号一样了,剩下的有用的内置变量比如OFS(output field separator)(默认为空格),是用在print 的“,”间插入的分隔符,ORS(output record separator)(默认为\n)是用作print语句结尾之后插入的符号

另一个特点,awk其实的主结构是这样的

BEGIN{
    # pre-process block
}
{
    # main process block
}
END{
    # post-process block
}

一般的东西都会在main的block里面搞定,但是main block是针对行为单位的,每个行都会执行一次main block里面的东东。BEGIN block里面的东西是在main之前,一次性执行的东西,所以一些变量的初始化之类的动作就特别适合在这个block里面进行,而END block里面是要在main的每行处理之后,一次性的在结束的时候进行处理的东西。需要处理的文件1为

 1 XXXX  
 2 XXXXXX
 3 01
 4 Notch: Down
 5 
 6 Total die count: 2663
 7 Good die count: 2578
 8 Yield: 96.8%
 9 
10 .......................111111111111......................
11 ...................1111111111111111111...................
12 .................111111111111111111x1111.................
13 ...............x111x1111111111111x1111111x...............
14 .............1111111111111111111111111111111.............
15 ............111111111111111111111111111111111............
16 ...........111111111111111111111111111111111111..........
17 ..........11111111111111111111111111111111111111.........
18 .........1111111111111111111111111111111111x11111........
19 ........111111111111111111111111111111111111111111.......
20 .......111111111111111111111111111111x1111x11111111......
21 ......11111111111111111111111111111111111111111111x......
22 .....1111111111111111111111111111x1111111111111111x......
23 .....111111111111111111111111111111111x1111x111111x......
24 ....111111x1111111111111111111111111111111111111x11xx....
25 ....11111111111111111111111111111111111111111111x11x11...
26 ...11111111111111111111111111111111111x111111111111111...
27 ...1111111111111111111111111111111111111111111111111111..
28 ..11111111111111111111111111111111111111111111111111111..
29 ..11111111111111111111111111111111111111111111111111111x.
30 .11111111111111111111111111111111111111x1111111111111111.
31 .11111111111111111111111111111111111111111111111x1111111.
32 .1111111111111111111111111111111111111111111111111111111.
33 .11111111111111111111111111111111111111111x11111111111111
34 x111111111111111111111111111111111111x1111111111111111111
35 111111111111111111111111111111111111111111111111111111111
36 1111111111111111111111111x1111111111111111111111111111111
37 111111111111111111111111111111111111111111111111111111111
38 1111111111111111111111111111111111111111x1111111111111111
39 11111111111x11111111111111111111111111111111111111111111x
40 1111111111111111111111111111111111111111x1111111111111111
41 1111111111111111111111111111111111111111111111x1111111111
42 111111111111111111111111111111111111111111111111111111111
43 111111111111111111111111111111111111111111111111111111111
44 1111111111111111111111111111111x1111111111111111111111111
45 .11111111111111111111111111111111111111111111111111111111
46 .111111111111111x1111111111111111x11111111111111111111111
47 .111111111111111111111111111111111111111111x1111x1111111.
48 .111111111111111x111111111111111x1111111111111111x111111.
49 ..111x111111111111111111111111111111111111111111111111x1.
50 ..1111111111x1xx11111111111111111xx11111111111x111111x1..
51 ...1111111111111111111111111111111111111111111111x11111..
52 ...111111111111xx11111111111x11111xx1111111111111111x1...
53 ...1111111111111111111111111111111x111111111x1111x1111...
54 ....111111111111xx111111111111111111x1x111x11111x1111....
55 ......1111111111111111111111111111111111111111x1x1111....
56 ......x11111111111xx111111111111111111x1111111111111.....
57 ......x1111111111111111111111111111111111111111111x......
58 .......111111111111xx111111111111111111x11111111111......
59 ........111111111111111111111111111111111111111111.......
60 ........111111111111xx11111111x111111111111111111........
61 .........111111111111111111111111111111111111111.........
62 ...........11111111x111x11111111111111111111111..........
63 ............1111111111111111111111111111111111...........
64 .............111111111111x111111x11111111111.............
65 ...............1111111111111111111111111111..............
66 ................1111111111111111111111111................
67 ...................11111111111111111111..................
68 ......................11111111111x11.....................

文件2为

  1 Product name = 115-XXXXXXXX
  2 Lot     name = XXXXXX
  3 Wafer-ID     = 01
  4 WF Start time= 2012-XX-XX 00:21:37
  5 WF End   time= 2012-XX-XX 00:54:15
  6 X max coor.  = 60
  7 Y max coor.  = 61
  8 Flat         = DOWN
  9 
 10 [ Wafer Map ]
 11                         #############
 12                     ####BYYYYYYYYYYB####
 13                   ##YYYYYYYYYYYYYYCYYYY####
 14                 ##BYYYYYYYYYYYBYYYYYYYYYY####
 15               ##YYYYBYYYYYYYYYYYBYYYYYYYYYY###
 16              #YYYBYYYYYYYYYYYYYYYYYYYYYYYYYYY###
 17            ##YBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY###
 18           ##YYYYYYYYYYYYYYCBYYYYYYYYYYYYBYYYYYYY##
 19          ##YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 20         ##YYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 21        ##YYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 22        #YYYYYYYYBYYYYYYYYYYYYYYYYYYYYYCYYYYYYYYYYYYC##
 23       #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYA###
 24      #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYA###
 25      #YYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYA####
 26     #YYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYAA##
 27    ##YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 28    #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 29    #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYYBBYYYYYYYYYYYYYC##
 30   #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 31   #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 32  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYY##
 33  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 34  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYY##
 35  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYY##
 36  BYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYCYYYYY##
 37 #YYYYYYYYYYYYYBYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 38 #YBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 39 #YYYYYYYYYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYCYYB##
 40 #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 41 #YYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 42 #YYYYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYCYYYYYYYYC##
 43 #CYYBYYCYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYYYYBYY##
 44 #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 45 #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYY##
 46 #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYBYYYYYYYYYYYYYYYYYYYY##
 47  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCYYY##
 48  #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYBYYYYY##
 49  #YYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 50  #YYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYY##
 51   #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYC##
 52   #YYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBY##
 53   ##YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 54    #YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBY###
 55    #YYYYBYYYYYYYYYYYYYYYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYY##
 56     #AAYYYYYYYYYYYYYYYYYYYYYYBBYYYYYYYYYYYYYYYYYYYYYBY###
 57     ###AYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 58      ##ABYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYCY##
 59       #ABYYYYYYYYYYYYYYBYYYYYYYYYBYYYYYYYYYYYYYYYYYY###
 60       ##CYYYYYYYYYYYYYYYYBYYYYYYYYYYYYBYYYYYYYYYYYYY##
 61        ##YYYYYYYYYYYYYYYYYYYYYYCYYYYYYYYYYYYYYYYYYC##
 62         #YYYYYYBYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY##
 63          #CYYYYYYYYYYYYYYYYYCYYYYYYYYBYYYYYYYYYYY##
 64           ##YYYYCYYYYYCYYYYYYYYYYYYYYYYYYYYYYYYY##
 65            ##YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYBY##
 66             ##YYYYYYYYYYYYYYYYYYYBYYYBYYYYBYY###
 67               ##YYYYYYYYYYYYYYYYYYYYYYYYYYYY###
 68                ##CYYYYYYYYYYYYYYYYYBYYYYYY###
 69                  ###YYYYYYYYYYYYCYYYYBYY###
 70                    ####BYYYYYYYYYYYYY####
 71                        ###############
 72 
 73 [ Wafer Bin Summary ]
 74 
 75 pass die :2563
 76 fail die :100
 77 totel die:2663
 78 
 79 BIN   A         10         0.38%
 80 BIN   B         61         2.29%
 81 BIN   C         29         1.09%
 82 BIN   Y       2563        96.24%
 83 #
 84 #
 85 #
 86 #
 87 #
 88 #
 89 #
 90 #
 91 #
 92 #
 93 #
 94 #
 95 #
 96 #
 97 #
 98 #
 99 #
100 #
101 #
102 #
103 #
104 #
105 #
106 #
107 #
108 #
109 #
110 #
111 #
112 #
113 #
114 #

 

基本的东西还是看例子,主要是两个wafer的文本图片,需要比较。BEGIN里面定义的都是一些初始化的变量,取第一个文件的10-68行,第二个文件的12-70行进行比较,为了格式,有71-74行的dummy行来调格式

 1 BEGIN{
 2     data_lines  =   59                              # valid data line-numbers
 3     a_index     =   1
 4     b_index     =   1
 5     d_index     =   1
 6     a_start     =   10                              # valid lines range
 7     a_end       =   68
 8     b_start     =   12                              # valid lines range
 9     b_end       =   70
10     d_start     =   71                              # dummy format lines range
11     d_end       =   74
12     pass        =   0                               # pass die
13     fail        =   0                               # fail die
14     space_lines =   36                              # blank lines
15 }

 

 

那main要干嘛呢,其实就是把两个文件的行分别读到不同的两个字符数组里面,为了在END里面对他们进行处理

 1 {
 2     if(x != ARGIND){                                # for different files line number set to 1
 3         NR = 1
 4     }
 5     x = ARGIND
 6 
 7     gsub(/\r/, "", $0)                                              # dos2unix
 8     if(ARGIND == 1 && NR >= a_start && NR <= a_end){                # data input
 9         a[a_index] = $0
10         a_index++
11     } else if(ARGIND == 2 && NR >= b_start && NR <= b_end){         # data input
12         b[b_index] = $0
13         bt = $0
14         b_sub[b_index] = gensub(/^.*[A-Z]([ #])/, "\\1", "g", bt)   # subfix of the line
15         bt = $0
16         b_pre[b_index] = gensub(/([ #])[A-Z].*$/, "\\1", "g", bt)   # prefix of the line
17         b_index++
18     } else if(ARGIND == 2 && NR >= d_start && NR <= d_end){         # dummy format lines
19         d[d_index] = $0
20         d_index++
21     }
22 }

这里面比较tricky的地方就是如何判断文件是读到了第一个的行还是第二个的行,因为ARGIND会指示到了哪个文件指针,但是NR会一直记下去,所以只要上次的文件指针和这次的文件指针不同,那么我就认为现在到了第二个文件的第一行,那么就将NR清零就好了。这就是2-5行做的事情。

比较别扭的是不知为啥读进来的文件默认都成了windows的格式,所以7行干的是一个转换的功能。8-20行就要把数据依次存入所要的字符数组里面了,这里因为格式必须要和文件2的wafer图一致,就先把不相关的prefix和subfix都remove掉,拿到真正的数据再进行处理,这样就方便了,这里牵扯到了替换函数,awk有三个吧(至少),sub每行替换一次会改变源字符串,gsub每行替换所有改变源字符串,gensub很厉害可以选择替换的方式和个数,但是不改变源字符串,能用match variable不知道是不是只能是gensub,反正前面两个我是没有成功,而且奇怪的是1号变量要用\\1,而不是\1,这点需要注意。

好数据都拿到了就需要到END的模块内统一进行处理了,先把格式统一,都变成只有Y和X的块,去掉多余的空格,之后根据每次字符比较的结果决定输出的字符是什么

 1 END{
 2     for(j=1; j <= data_lines; j++){                 # format the first array to be processed
 3         gsub(/\./, " ", a[j])
 4         gsub(/1/, "Y", a[j])
 5         gsub(/x/, "X", a[j])
 6         gsub(/^ +/, "", a[j])
 7         gsub(/ +$/, "", a[j])
 8     }
 9     for(j=1; j <= data_lines; j++){                 # format the second array to be processed
10         gsub(/#/, " ", b[j])
11         gsub(/B/, "X", b[j])
12         gsub(/A/, "X", b[j])
13         gsub(/C/, "X", b[j])
14         gsub(/^ +/, "", b[j])
15         gsub(/ +$/, "", b[j])
16     }
17 
18     for(j=1; j <= data_lines; j++){                 # summary for the yield
19         r[j] = str_com(a[j], b[j])
20         pass += str_cnt(r[j], "Y")
21         fail += str_cnt(r[j], "A")
22     }
23     for(j=1; j <= data_lines; j++){                 # print the compare lines
24         print b_pre[j] r[j] b_sub[j]
25     }
26     for(j=1; j <= (d_end - d_start + 1); j++){      # print the dummy format lines
27         print d[j]
28     }
29     print "Pass die :" pass                         # report the result
30     print "Fail die :" fail
31     print "Totel die:" pass+fail
32     printf("Yield: %.2f%\n", pass/(pass+fail)*100)
33     for(j=1; j <= space_lines; j++){                # print the dummy format lines
34         print "#"
35     }
36 }

这里面需要用到两个自己写的函数,一个是输出每行有多少个特定字符的函数,一个是比较输出字符串的函数

 1 function str_cnt(str_0, char_0){                    # count the character in one line
 2     x_0 = 0
 3     for(i=1;i<=length(str_0);i++){
 4         st_0 = substr(str_0, i, 1)
 5         if(st_0 == char_0){
 6             x_0++
 7         }
 8     }
 9     return x_0
10 }
11 #-------------------------------------------------------------------------------
12 function str_com(str_1, str_2)                      # compare lines in curtain format
13 {
14     str_r = ""
15     for(i=1;i<=length(str_2);i++){
16         st_1 = substr(str_1, i, 1)
17         st_2 = substr(str_2, i, 1)
18         if(st_1 == st_2){
19             if(st_2 == "X"){
20                 gsub(/(.*)/, "&A", str_r)
21             }else if(st_2 == "Y"){
22                 gsub(/(.*)/, "&Y", str_r)
23             }
24         }else{
25             gsub(/(.*)/, "&A", str_r)
26         }
27     }
28     return str_r
29 }

好了,大体就这样,那么如果有25个这样的文件要如何用脚本一次性的比较完呢?

#! /bin/csh -f
set end     =   25
set temp    =   1
mkdir -p D3J250_3
while ($temp <= $end)
    sed -e '12,$d;4s/.*//g;5s/.*//g' ./D3J250_2/D3J25${temp}.txt > ./D3J250_3/${temp}.out
    awk -f com.awk ./D3J250_1/D3J25${temp}.asc ./D3J250_2/D3J25${temp}.txt >> ./D3J250_3/${temp}.out
    printf %d $temp
    printf %s " file processed"
    awk -f diff.awk ./D3J250_merge/${temp}.txt ./D3J250_3/${temp}.out
    @ temp++
end
dos2unix -q ./D3J250_3/*

就是这样,因为在D3J250_merge里面有原来生成的比较文件,想diff一下是否一致,所以又写了一个diff的小脚本

 1 BEGIN{
 2     a_index = 1
 3     b_index = 1
 4     flag    = 0
 5 }
 6 {
 7     if(x != ARGIND){
 8         NR = 1
 9     }
10     x = ARGIND
11     gsub(/\r/, "", $0)
12     if(ARGIND == 1){
13         a[a_index] = $0
14         a_index++
15     }else if(ARGIND == 2){
16         b[b_index] = $0
17         b_index++
18     }
19 }
20 END{
21     for(j=1; j<=b_index; j++){
22         if(a[j] != b[j]){
23             flag = 1
24         }
25     }
26     if(flag == 1){
27         print " COMPARING...\t\t<---DIFFERENT--->!!!!"
28     }else if(flag == 0){
29         print " COMPARING...\t\t####IDENTICAL####"
30     }
31 }

就是这样,没啥特别的。

 

另一个awk的脚本是将10个csv的文本文件每行都粘贴至一起的脚本,同时由于是模拟量,还需要一个小替换,BEGIN还是用来初始化一些基本的变量,由于是csv,所以FS要设置成",",而数据是从2-600行,one的值为1.800,zero的值为0.00000,就这样

 1 BEGIN{
 2     error_flag = 0
 3     start_line = 2
 4     end_line   = 600
 5     one_value  = "1.800"
 6     zero_value = "0.00000"
 7     FS = ","
 8     inx9 = 0
 9     inx8 = 0
10     inx7 = 0
11     inx6 = 0
12     inx5 = 0
13     inx4 = 0
14     inx3 = 0
15     inx2 = 0
16     inx1 = 0
17     inx0 = 0
18 }

main要干什么呢?还是数据的读入

 1 {
 2     if(x != ARGIND){
 3         NR = 1
 4     }
 5     x = ARGIND
 6     gsub(/\r/, "", $0)
 7     gsub(zero_value, "0", $0)
 8     gsub(one_value, "1", $0)
 9 
10     if(ARGIND == 1 && NR >= start_line && NR <= end_line){
11         d9[++inx9] = $2
12     }else if(ARGIND == 2 && NR >= start_line && NR <= end_line){
13         d8[++inx8] = $2
14     }else if(ARGIND == 3 && NR >= start_line && NR <= end_line){
15         d7[++inx7] = $2
16     }else if(ARGIND == 4 && NR >= start_line && NR <= end_line){
17         d6[++inx6] = $2
18     }else if(ARGIND == 5 && NR >= start_line && NR <= end_line){
19         d5[++inx5] = $2
20     }else if(ARGIND == 6 && NR >= start_line && NR <= end_line){
21         d4[++inx4] = $2
22     }else if(ARGIND == 7 && NR >= start_line && NR <= end_line){
23         d3[++inx3] = $2
24     }else if(ARGIND == 8 && NR >= start_line && NR <= end_line){
25         d2[++inx2] = $2
26     }else if(ARGIND == 9 && NR >= start_line && NR <= end_line){
27         d1[++inx1] = $2
28     }else if(ARGIND == 10 && NR >= start_line && NR <= end_line){
29         d0[++inx0] = $2
30     }
31 }

接着END来做数据的结合工作,如果行数不一样,就不做处理报错,如果一致的话就粘起来。

 1 END{
 2     if(inx9 != inx8 || inx8 != inx7 || inx7 != inx6 || inx6 != inx5 || inx5 != inx4 ||
 3        inx4 != inx3 || inx3 != inx2 || inx2 != inx1 || inx1 != inx0){
 4            error_flag = 1
 5            print "NOT IN ONE LENGTH"
 6            print "REFUSE TO PROCESS"
 7     }
 8     if(error_flag != 1){
 9         for(j=1;j<=inx9;j++){
10             res[j] = d9[j] d8[j] d7[j] d6[j] d5[j] d4[j] d3[j] d2[j] d1[j] d0[j]
11             print res[j]
12         }
13     }
14 }

至此,文件转换就结束了,如何调用呢?还是用个csh来搞

1 #! /bin/csh -f
2 find . -name "d*.csv" | sort -r | xargs awk -f ./cat.awk > data_bin.txt
3 echo "Processing..."
4 cat data_bin.txt | awk '{system("echo \"" "obase=10; ibase=2; " $0 "\" | bc")}' > data_dec.txt

这里面就用到了许多繁琐的东西,包括xargs,和bc,试用下吧,自己体会一下就好,bc是可以完成十进制转换二进制的~

posted @ 2012-09-30 11:25  poiu_elab  阅读(1704)  评论(0编辑  收藏  举报