【细心钻研】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是可以完成十进制转换二进制的~