AWK的结构是模式-动作;可以理解为条件-动作。举个简单的例子:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '$3>0 {print $1,$2*$3}'
Kathy 40
Mark 100
Mary 121
Susie 76.5
这里$3>0是条件,顺序是先执行条件再去执行动作。 两者的关系是并的关系。
AWK程序运行结构
awk的运行实际上是按行进行运行的,它是陆续的扫描每一行,找到可以匹配的项{默认的分割符是一个空格}。比如:
[root@cuiyf opt]# awk '{print $1}' test
Beth
Dan
Kathy
Mark
Mary
Susie
表示每行扫描打印第一个单位$1。
一些简单的了解:
1
全环境打印:
{print} {print $0}
2
打印某些字段:
{print 1, 2}
3
计算一行中有多少个字段
{print NR}
例子:
[root@cuiyf opt]# cat 123
aa 1
bb
[root@cuiyf opt]# cat 123 | awk '{print NF}'
2
1
第一行有两个字段,第二行有一个字段。
4
计算和打印
{print 1, 2*$3} 数字和字符串相互乘,不报错但是逻辑上不正确。
[root@cuiyf opt]# cat test | awk '{print NR,$0,"is ok !"}'
1 Beth 4.00 0 is ok !
2 Dan 3.75 0 is ok !
3 Kathy 4.00 10 is ok !
4 Mark 5.00 20 is ok !
5 Mary 5.50 22 is ok !
6 Susie 4.25 18 is ok !
5
计算行号
可以使用内置的函数NR进行计算,比如:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '{print NR,$0}'
1 Beth 4.00 0
2 Dan 3.75 0
3 Kathy 4.00 10
4 Mark 5.00 20
5 Mary 5.50 22
6 Susie 4.25 18
6
字符串和变量一起输出,比如:
[root@cuiyf opt]# cat test | awk '{print NR,$0,"is ok !"}'
1 Beth 4.00 0 is ok !
2 Dan 3.75 0 is ok !
3 Kathy 4.00 10 is ok !
4 Mark 5.00 20 is ok !
5 Mary 5.50 22 is ok !
6 Susie 4.25 18 is ok !
华丽的输出之printf
1
{printf(“total pay for %s is 1, 2∗ 3)}
执行如下的操作:
%s 是确定$1为字符串模式,%.2f表示取小数点和两位,f浮点类型。这里主要是正则表达式方面的注意一下printf需要有\n。
2
{printf(“%-8s 1, 2∗ 3)}
执行如下的操作:
[root@cuiyf opt]# cat test |awk '{printf("%-8s $%6.2f\n",$1,$2*$3)}'
Beth $ 0.00
Dan $ 0.00
Kathy $ 40.00
Mark $100.00
Mary $121.00
Susie $ 76.50
这个说明Beth到$有8个字符;$到最后一个0有6个字符
AWK对模式的考虑
模式也可以理解为条件:从以下的几个方面考虑
1
通过比较进行选择
$2*$3>50
[root@cuiyf opt]# cat test | awk '$2*$3>50 {print $0}'
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
2
通过文本的内容进行选择
$1=="Mark"
[root@cuiyf opt]# cat test | awk '$1=="Mark" {printf("%-8s %5.2f %5d\n"),$1,$2,$3}'
Mark 5.00 20
3
使用模式组合{或,且,和}{&&;||;!}
$2>5 || $3>20
[root@cuiyf opt]# cat test | awk '$2>5 || $3>20 {printf("%-10s %5.2f %5d\n",$1,$2,$3)}'
Mary 5.50 22
4
BEGIN和END
加上BINGEN的话会在第一行上匹配出对应需要匹配的行,END反之。例子:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk 'BEGIN{print "SSS AAA NNN"}{print$0 }'
SSS AAA NNN
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
5
AWK计算问题
一个动作就是一个语句,每个动作需要使用换行符来区分或者是使用;分隔符来区分。
在计算上不仅是可以使用内置的变量,而且是可以使用自己定义的变量。但是需要知道的是awk不需要申明变量的类型。
计数:
例子:{自创的变量}
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '$3 > 5 {sum = sum + 1}END{print sum ,"TEXT" "test"}'
4 TEXTtest
[root@cuiyf opt]# cat test | awk '$3 > 5 {sum = sum + 1};END{print sum ,"TEXT" "test"}'
4 TEXTtest
计算总和和平均数问题
总和计算人数可以使用内置参数NR。例子:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk 'END{print NR}'
6
平均数利用所学总和输出:
例子:
[root@cuiyf opt]# cat test | awk '{sum = sum + $2*$3}END{printf("%-5d %-5.2f %-5.2f\n", NR,sum,sum/NR)}'
6 337.50 56.25
文本的操作与演示:
选出最大值:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '$2>cui {cui = $2;you = $1}END{print cui,you}'
5.50 Mary
字符串的拼接
对于拼接的理解实际上就是将竖行的字符串组成一个行的内容。例子:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test |awk '{name =name $1 " "}{print name}'
Beth
Beth Dan
Beth Dan Kathy
Beth Dan Kathy Mark
Beth Dan Kathy Mark Mary
Beth Dan Kathy Mark Mary Susie
[root@cuiyf opt]# cat test |awk '{name =name $1 " "}END{print name}'
Beth Dan Kathy Mark Mary Susie
AWK的内建函数
length:主要用来计算字符串中字符的个数。
例子:
[root@cuiyf opt]# awk '{print $1, length($1) }' test
Beth 4
Dan 3
Kathy 5
Mark 4
Mary 4
Susie 5
行,单词与字符的统计
使用length和NR和NF;例子:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '{cui=cui+length($0)+1 ; you=you+NF}END{print NR,cui,you}'
6 77 18
其中:NR统计行;cui统计的是字符数;you统计的是单词。{NF 统计一行中有 多少的单词}
控制语句流程
控制语句只能用在动作中 。需要注意不是模式中。
If-Else语句;例子:
[root@cuiyf opt]#
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '$2>5{n=n+1;y=$2*$3}{if(n>0) print n,y;else print "no"}'
no
no
no
no
1 121
1 121
WHILE语句
while判断当为真的时候,循环继续。
公式:y=a(1+x)^i
[root@cuiyf ~]# cat aaa
1000 0.06 5
[root@cuiyf ~]# cat aaa | awk '{i=1 }{while(i<=5){printf("\t%.2f\n",$1*(1+$2)^i );i=i+1}}'
1060.00
1123.60
1191.02
1262.48
1338.23
FOR语句实现WHILE语句的功能
[root@cuiyf ~]# cat aaa | awk '{for (i=1;i<=$3;i=i+1){printf("\t%.2f\n", $1*(1+$2)^i)}}'
1060.00
1123.60
1191.02
1262.48
1338.23
注意一下WHILE和FOR的区别。
数组的简单使用:
数组的功能很强大;这里简单的写一个例子实现文件顺序倒写:
[root@cuiyf opt]# cat test
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
[root@cuiyf opt]# cat test | awk '{line[NR]=$0}END{i=NR;while(i>0){print line[i];i=i-1}}'
Susie 4.25 18
Mary 5.50 22
Mark 5.00 20
Kathy 4.00 10
Dan 3.75 0
Beth 4.00 0
+++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++
基本上AWK的简单的介绍算是完毕了 ;总结一下常用的一些用法:
1. 输入行的总行数
END{ print NR }
2. 打印第 10 行
NR == 10
3. 打印每一个输入行的最后一个字段
{ print $NF }
4. 打印最后一行的最后一个字段
{ field = $NF }
END { print field }
5. 打印字段数多于 4 个的输入行
NF > 4
6. 打印最后一个字段值大于 4 的输入行
$NF > 4
7. 打印所有输入行的字段数的总和
{ nf = nf + NF }
END { print nf }
8. 打印包含 Beth 的行的数量
/Beth/ { nlines = nlines + 1 }
END { print nlines }
9. 打印具有最大值的第一个字段, 以及包含它的行 (假设 $1 总是 正的)
$1 > max { max = $1; maxline = $0 }
END { print max, maxline }
10. 打印至少包含一个字段的行
NF > 0
11. 打印长度超过 80 个字符的行
length($0) > 80
12. 在每一行的前面加上它的字段数
{ print NF, $0 }
13. 打印每一行的第 1 与第 2 个字段, 但顺序相反
{ print $2, $1 }
14. 交换每一行的第 1 与第 2 个字段, 并打印该行
{ temp = $1; $1 = $2; $2 = temp; print }
15. 将每一行的第一个字段用行号代替
{ $1 = NR; print }
16. 打印删除了第 2 个字段后的行
{ $2 = ""; print }
17. 将每一行的字段按逆序打印
{ for (i = NF; i > 0; i = i - 1) printf("%s ", $i)
printf("\n")
}
18. 打印每一行的所有字段值之和
{ sum = 0
for (i = 1; i <= NF; i = i + 1) sum = sum + $i
print sum
}
19. 将所有行的所有字段值累加起来
{ for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
END { print sum }
20. 将每一行的每一个字段用它的绝对值替换
{ for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i
print
}