整理翻译。原文地址:http://www.hcs.harvard.edu/~dholland/computers/awk.html
简明awk教程
- 为什么选awk?
awk小巧、快速、简单。awk语言简练,像C。它用来进行文本处理,非常方便。
- awk能用来干嘛?
awk设计用来处理基于“列”构成的文本数据,例如表格。变量$1,$2..代表输入数据的第1、2..列。例如,要打印一个文件的第2列,你可以:
awk < file '{print $2}'
这句是说“对于每一行,打印第2列”。
同时还要打出第3列,你可以:
awk < file '{print $2,$3}'
- 输入分割符
默认情况下,awk用空白符(空格、Tab)来分割输入数据。你可以使用 -F 参数来制定分割符。举个例子,打印linux中每个用户的主目录,你可以:
awk < /etc/passwd -F: '{print $6}'
passwd文件中,每个用户的各种信息是用冒号来分割,而第6个是用户主目录。
- 数学运算
awk不强调变量的类型。变量根据被引用情况,要么是字符串,要么是数值。所有数值变量都是浮点型。以下实现华氏向摄氏的计算:
awk '{print ($1-32)*(5/9)}'
这句话将一直处理标准输入的数值,直到被终止。
运算符和C语言中的使用差不多。相邻的字符串变量即可拼接,而 ‘+’则总表示数值上的加法。因此:
echo 5 4 | awk '{print $1+$2}'
输出 9,而
echo 5 4 | awk '{print $1 $2}'
输出 54。需要注意的是
echo 5 4 | awk '{print $1,$2}'
输出 5 4。(5和4中间有空格)
- 变量
awk有一些内建的变量,$1、$2已经提到。同样对初学者很有用的变量是NF,它给出总列数(这样的话,$NF就表示最后一列)。$0表示所有输入数据。
你也可以创建变量,但不需要声明它们。没显式赋值的字符串初值是"",数值则是0。
举个例子,下面这句打印出了每行数据的平均数:
awk '{tot=0; for(i=1;i<=NF;i++) tot+=$i; print tot/NF;}'
需要注意的是,这里$i获得第i个数据,for循环则很像C语言。这里给tot赋0值是为了处理每行前重置,不把上一行的处理结果带入计算中。
- 语句块
若是每行一个数据,又该怎么计算他们的平均数呢?你可这么做:
awk '{tot+=$1; n+=1;} END {print tot/n;}'
上面两个语句块之间的“END”表明紧随其后的语句块要在所有行数据处理完毕之后才执行。类似的,如果语句块前出现条件语句,条件成立方可执行。如:
awk '$1==0 { pirnt $2}'
这句是说,当第1列数据为0时,打印出第2列。还有,你可以使用正则表达式:
awk '/^test/ {print $2}'
总之,语句块前,如果没有任何表达式,那么它总要执行;如果条件成立,那么它也执行;需要说明的是,没有特别干脆的方法,能实现选择各语句块中的一个去执行。
“BEGIN”和“END”一样,是个特殊的块语句执行条件,它指明在所有数据处理前执行。
- 其他语言结构
awk支持类似C语言的循环和条件语句:for,while,do/while,if,和 if/else。
- printf
awk中printf同C语言中功能相似。因此,它可以用来漂亮地输出、复杂地打印。(前面的print 会自动在输出结果后加上换行;printf不会。)
下面的例子用来删去第1列:
awk '{for(i=2; i<=NF; i++) printf "%s ", $i; printf " ";}'
- 配合其他工具
脚本语言的好处在于可以轻松配合其他工具使用。一些工具很容易通过管道使用awk进行后续处理。awk也多与sed一起组合,用于正则的匹配和替换。
同sed, sort, paste等工具一起使用之后,awk在数据处理方面得心应手,在列表格式的数据库维护方面也相当不错。
别用csh,用sh或者ksh。
如何查看你使用频率最高的linux命令:
history | awk '{CMD[$2]++;count++;} END { for (a in CMD )print CMD[ a ]" " CMD[ a ]/count*100 "% " a }'| grep -v "./"| column -c3 -s " "-t |sort -nr | nl | head -n10
- 再说一些
这个教程相当简单、基础,awk其实可以做许多有用的事。man手册页中关于awk的部分是很好的参考。