Awk是功能完整的文本处理语言, 使用类似于C的语法. 它具有一整套操作符和能力集, 我们只在这里讲解一小部分 - 也就是在shell脚本中最有用的部分.
Awk将传递进来的每行输入都分割成域. 默认情况下, 一个域指的就是使用空白分隔的一个连续字符串, 不过我们可以修改属性来改变分隔符. Awk将会分析并操作每个分割域. 因为这种特性, 所以awk非常善于处理结构化的文本文件 -- 尤其是表 -- 将数据组织成统一的块, 比如说分成行和列.
强引用(单引号)和大括号用来包含shell脚本中的awk代码段.
1 echo one two | awk '{print $1}' 2 # one 3 4 echo one two | awk '{print $2}' 5 # two 6 7 8 awk '{print $3}' $filename 9 # 打印文件$filename的域#3, 到stdout. 10 11 awk '{print $1 $5 $6}' $filename 12 # 打印文件$filename的域#1, #5, 和#6. |
事实上, 上边我们只讲解了awk的print命令. 我们需要在这里讲解awk的另一个特点, 变量. Awk处理变量的手段与shell脚本很相似, 虽然更复杂一些.
1 { total += ${column_number} } |
1 END { print total } |
与END对应, 还有BEGIN命令块, 在脚本处理所有输入之前, 将会执行这个命令块中的内容.
下面这个例子展示了awk如何在shell脚本中添加文本分析工具.
例子 C-1. 计算字符出现次数
1 #! /bin/sh 2 # letter-count2.sh: 在文本文件中计算字符的出现次数. 3 # 4 # 由nyal [nyal@voila.fr]编写. 5 # 授权使用. 6 # 本文作者重新注释. 7 # 版本 1.1: 经过修改可用于gawk 3.1.3. 8 # (也可用于awk的早期版本.) 9 10 11 INIT_TAB_AWK="" 12 # 初始化awk脚本的参数. 13 count_case=0 14 FILE_PARSE=$1 15 16 E_PARAMERR=65 17 18 usage() 19 { 20 echo "Usage: letter-count.sh file letters" 2>&1 21 # 比如: ./letter-count2.sh filename.txt a b c 22 exit $E_PARAMERR # 传递到脚本的参数个数不够. 23 } 24 25 if [ ! -f "$1" ] ; then 26 echo "$1: No such file." 2>&1 27 usage # 打印使用信息并退出. 28 fi 29 30 if [ -z "$2" ] ; then 31 echo "$2: No letters specified." 2>&1 32 usage 33 fi 34 35 shift # 指定的字符. 36 for letter in `echo $@` # for循环遍历 . . . 37 do 38 INIT_TAB_AWK="$INIT_TAB_AWK tab_search[${count_case}] = \"$letter\"; final_tab[${count_case}] = 0; " 39 # 作为参数传递到下边的awk脚本中. 40 count_case=`expr $count_case + 1` 41 done 42 43 # 调试: 44 # echo $INIT_TAB_AWK; 45 46 cat $FILE_PARSE | 47 # 将目标文件通过管道传递下边的awk脚本中. 48 49 # ---------------------------------------------------------------------------------- 50 # 下边是本脚本的早期版本使用的方法: 51 # awk -v tab_search=0 -v final_tab=0 -v tab=0 -v nb_letter=0 -v chara=0 -v chara2=0 \ 52 53 awk \ 54 "BEGIN { $INIT_TAB_AWK } \ 55 { split(\$0, tab, \"\"); \ 56 for (chara in tab) \ 57 { for (chara2 in tab_search) \ 58 { if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \ 59 END { for (chara in final_tab) \ 60 { print tab_search[chara] \" => \" final_tab[chara] } }" 61 # ---------------------------------------------------------------------------------- 62 # 不是所有的都那么复杂, 只是 . . . 63 #+ for循环, if条件判断, 和几个指定函数而已. 64 65 exit $? 66 67 # 与脚本letter-count.sh相比较. |
如果想再看一些在shell脚本中使用awk的简单例子, 如下:
我们在这里所要讲解的awk内容就这么多, 但是事实上还有好多东西需要学. 可以参考参考文献中的内容深入学习.