UNIX环境下,用shell做一些常见的文本处理工作是很方便高效的事情;虽然目前有很多自带丰富类库的脚本语言可以完成同样的事情,但是对于一些特殊的文本格式处理任务,传统的sed/awk/grep组合还是有很明显的优势:没有复杂的版本问题和类库部署依赖问题,能够快速解决问题。awk作为一门DSL ,自身也带有对很多高级特性 (相对于shell本身)的支持,灵活应用往往能收到奇效。
array类型 
awk自身支持类似于C语言数组的数据结构,称之为array ,但是其下标却不仅仅限于数字,可以是字符串等其它类型;行为上来说更似于一个关联容器,从某个变量关联到另外一个变量:
1 
2 
3 
4 
5 
awk 'BEGIN{ 
     arr[' aa'] = 1 
    arr[4] = 2 
    print arr[' aa'] 
}' 
 
基本的array操作:
1 
2 
3 
4 
5 
6 
7 
8 
awk 'BEGIN{ 
     arr[1] = "cc" 
    arr[2] = "ddd" 
    arr[' ccd'] = "demo" 
    for (i in arr){ 
        print arr[i] 
    } 
}' 
 
多维数组 – 多个下表操作内部会被转换为SUBSEP 连接的字符串为索引的array: 
 
array.awk  (awk_array.awk)  download  
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
#!/usr/bin/awk -f 
BEGIN{ 
     for ( i  =  0; i < 10; i++){ 
         for ( j  =  0; j < 8; j++){ 
             grid[ i, j]  =  i * j;
         } 
     } 
     grid[ 1,2,7]  =  14;
     grid[ 4,2,7]  =  56;
 
     if  (  ( 1,2)  in grid){ 
         printf ( "grid[1][2]=%d\n" , grid[ 1,2]) ;
     } 
 
     for ( idx in grid){ 
         fmt  =  "grid[" ;
         n  =  split( idx, indices, SUBSEP) ;
         for  ( sub_idx  =  1; sub_idx <=  n; sub_idx++){ 
             fmt  =  fmt indices[ sub_idx]  "][" 
         } 
         printf ( "%s = %d\n" , substr( fmt, 1, length( fmt)  - 1) , grid[ idx]) 
     } 
 } 
 
需要获取具体下标的时候,可以使用split函数,传入SUBSEP 作为分隔符,依次取得每一个下标。用于数据统计的时候,这一技巧相当顺手好用。
字符串操作和正则表达式技巧 
字符串操作和C语言非常类似,可以使用:
substr 取得子串,和很多脚本语言类似,传入一个源字串,初始下标和长度,例如: 
 
1 
2 
3 
4 
5 
awk 'BEGIN{ 
     teststr = "this is a test string..." 
    printf("<%s>\n", substr(teststr, 1, length(teststr) - 1)); 
    printf("<%s>\n", substr(teststr, 0, length(teststr) - 1)); 
}' 
 
这里的第二个printf传入的下标从0开始,那么实际上得到的字串从末尾处被截去了2个字符。
正则表达式regexp 
基本的类sed 类操作正如其名称所示(部分操作可以省略源字符串,默认等同于和$0相匹配)
1 
2 
echo  "The lazy dog"  | awk '{sub(/[ey] /, "lagggg> ");print}' 
#Thlagggg> lazy dog 
 
gsub 用于全局替换,所有满足条件的部分都被替换 
 
1 
2 
echo  "The lazy dog"  | awk '{gsub(/[ey] /, "lagggg> ");print}' 
Thlagggg> lazlagggg> dog
 
 
gensub 是一个更通用形式的正则替换操作,它保持源字符串不动,将修改后的串返回 
 
1 
2 
3 
echo  "The lazy dog"  | gawk '{new = gensub(/[ey] /, "lagggg> ", "g");print; print new}' 
#The lazy dog 
#Thlagggg> lazlagggg> dog 
 
match 可用于模式匹配并返回匹结果的开始下标,并设置RSTART 为匹配到的下标,RLENGTH 为匹配字串的长度 
 
1 
2 
3 
4 
5 
6 
7 
echo  "The lazy dog jump over the brown fox"  | awk '{ 
result = match($0, /(dog)(.*)(fox)/) 
print result, RSTART, RLENGTH 
print substr($0, RSTART, RLENGTH) 
> }' 
#10 10 27 
#dog jump over the brown fox 
 
脚本内嵌和独立awk文件 
一般可以将不太长的awk脚本处理放入管道操作中,让后用'来包含实际的awk处理脚本。当awk脚本过长的时候或者为了便于维护,也可以用一个独立的脚本来存放awk脚本内容,但是其shebang部分应该设置为: #!/usr/bin/awk -f, 这里的 -f表示后边的内容是awk脚本文件。