awk是一种文本模式扫描和处理语言。它可能非常复杂所以本文不是一个完整的指南,但可以让你明白awk可以做什么。它使用起来可以非常简单,强烈推荐。网上有许多不同复杂程度的在线教程,当然,总是有“man awk”。
一个awk程序操纵输入文件的每一行。它有一个在处理文件内容之前的开始命令选项部分BEGIN{},main{}部分工作于文件的每一行,最后还有一个END{}部分选项在文件读完了执行。
BEGIN { …. 初始awk命令 …}
{ …. awk命令操纵文件的每一行…}
END { …. awk结束命令 …}
对于输入文件的每一行,如果有任意匹配模式说明,它只操作匹配该模式的行,否则它将会匹配所有行。这些模式匹配命令可以像grep一样包含正则表达式。awk命令能做一些十分复杂的数学和字符串操作,同时awk也支持关联数组。
awk把每一行看成是一个个字段组成的,每一行被’字段分割器‘拆分。通常是被一个或多个空格拆分的,所以下面这行:
this is a line of text
包含6个字段。在awk命令中,第一个字段指向$1,第二个字段指向$2,整行指向$0。字段分割器是被awk的内核变量FS设置的,所以如果你设置FS=":",行将会根据:所在位置来进行分割,这种设置对像 /etc/passwd一样的文件很有用。另一些有用的内核变量有用来记录当前行编号的NR,和记录当前字段在行中的编号NF 。
awk能操作任意类型的文件,包括键盘输入,在这种情况下它通常会和’|‘命令一起使用。例如,和grep或其它命令组合起来使用。例如我像下面这样列出所有文件:
[mijp1@monty RandomNumbers]$ ls -l
total 2648
-rw------- 1 mijp1 mijp1 12817 Oct 22 00:13 normal_rand.agr
-rw------- 1 mijp1 mijp1 6948 Oct 22 00:17 random_numbers.f90
-rw------- 1 mijp1 mijp1 470428 Oct 21 11:56 uniform_rand_231.agr
-rw------- 1 mijp1 mijp1 385482 Oct 21 11:54 uniform_rand_232.agr
-rw------- 1 mijp1 mijp1 289936 Oct 21 11:59 uniform_rand_period_1.agr
-rw------- 1 mijp1 mijp1 255510 Oct 21 12:07 uniform_rand_period_2.agr
-rw------- 1 mijp1 mijp1 376196 Oct 21 12:07 uniform_rand_period_3.agr
-rw------- 1 mijp1 mijp1 494666 Oct 21 12:09 uniform_rand_period_4.agr
-rw------- 1 mijp1 mijp1 376286 Oct 21 12:05 uniform_rand_period.agr
我们发现第5个字段是文件大小行,。所以如果我想知道上面所有文件的大小我可以这样写:
[mijp1@monty RandomNumbers]$ ls -l | awk 'BEGIN {sum=0} {sum=sum+$5} END
{print sum}'
2668269
注意’print sum’打印变量sum的值,所以如果sum=2则输出2,然而’print $sum’将会打印1,因为第二个字段包含值1。
因此可以直接写一个awk命令去计算一栏数字的平均值和标准差-在main{}部分中累加’sum_x’和’sum_x2’,然后在END{}部分使用标准差公式计算平均值和标准差。
awk支持循环(for和while),也支持分支(if)。所以如果你想修剪一个文件并且只操作每行的第3个字段,你可以这样写:
[mijp1@monty RandomNumbers]$ ls -l | awk '{for (i=1;i<3;i++) {getline};
print NR,$0}'
3 -rw------- 1 mijp1 mijp1 6948 Oct 22 00:17 random_numbers.f90
6 -rw------- 1 mijp1 mijp1 289936 Oct 21 11:59 uniform_rand_period_1.agr
9 -rw------- 1 mijp1 mijp1 494666 Oct 21 12:09 uniform_rand_period_4.agr
10 -rw------- 1 mijp1 mijp1 376286 Oct 21 12:05 uniform_rand_period.agr
for循环使用getline命令在文件中移动,并且扫描3行(i<3,若为2则扫描2行)只打印一次。注意这个文件总共有10行,不能被3整除。最后命令提前终止了并且打印了第10行。同时我们适应NR变量打印了行号。
AWK模式匹配
AWK是面向行的语言,先有模式后有动作。动作语句包含在{和}中。可以没有模式或者是动作,但不能同时没有。如果缺失模式,动作将会执行输入流的每一个字段,缺失动作的将会打印整个记录。
awk模式包含正则表达式(和grep -E使用句法一样) 并且组合使用一些特殊的标记。&&代表逻辑与,||代表逻辑或,!表示非。您还可以执行关系模式、模式组、范围等。
AWK控制语句包括:
if(条件) 语句 [其它语句]
while(条件) 语句
do 语句 while(条件)
for(表达式1; 表达式2; 表达式3) 语句
for(变量 in 数组) 语句
break
continue
exit [表达式]
参考:https://www-users.york.ac.uk/~mijp1/teaching/2nd_year_Comp_Lab/guides/grep_awk_sed.pdf