首页 > 代码库 > 老男孩教育每日一题-2017年3月28日-awk累计相加
老男孩教育每日一题-2017年3月28日-awk累计相加
假如现在有个文本,格式如下:
a 1 b 3 c 2 d 7 b 5 a 3 g 2 f 6 d 9
即左边是随机字母,右边是随机数字,要求写个脚本使其输出格式为:
a 4 b 8 c 2 d 16 f 6 g 2
即将相同的字母后面的数字加在一起,按字母的顺序输出。
答案:
awk ‘{h[$1]=h[$1]+$2}END{for(pol in h)printpol,h[pol]}‘ array_add.txt
演示:
[root@show awkfile]# awk‘{h[$1]=h[$1]+$2}END{for(pol in h)print pol,h[pol]}‘ array_add.txt a 4 b 8 c 2 d 16 f 6 g 2
过程详解:
第一个里程碑-把第二列的数字的总和
[root@show awkfile]# cat array_add.txt a 1 b 3 c 2 d 7 b 5 a 3 g 2 f 6 d 9 [root@show awkfile]# awk ‘{sum=sum+$2}END{printsum}‘ array_add.txt 38
第二个里程碑-选择什么作为房间号码
这里只有两列,第一列是字母,第二列是数字是我们要相加的东西。这里我们选择第一列作为房间号码即元素名称。
第三个里程碑-遇到相同的字母再相加
这里就需要用到了awk数组的内容。
sum=sum+$2 这里把sum换成awk数组即可。
[root@show awkfile]# awk ‘{h[$1]=h[$1]+$2}‘array_add.txt
没有显示任何过程,不是很好。我们看看他到底如何处理的。一步一步来分析。注意这里我们只关注一个房间a,大家熟练后再同时看多个房间的内容。
[root@show awkfile]# awk ‘{h[$1]=h[$1]+$2;print"当前行内容:"$0,"a房间内容:"h["a"]}‘ array_add.txt 当前行内容:a 1 a房间内容:1 当前行内容:b 3 a房间内容:1 当前行内容:c 2 a房间内容:1 当前行内容:d 7 a房间内容:1 当前行内容:b 5 a房间内容:1 当前行内容:a 3 a房间内容:4 当前行内容:g 2 a房间内容:4 当前行内容:f 6 a房间内容:4 当前行内容:d 9 a房间内容:4
我们只关注a房间的内容及h["a"]的内容
行号 | 当前行的内容 | $1的内容 | $2的内容 | h["a"]之前的内容 | h["a"]=h["a"]+$2 | h["a"]之后的内容 |
1 | a 1 | a | 1 | 空 | h["a"]=空+1 | 1 |
2 | b 3 | b | 3 | 1 | 不是a房间,不进行计算,h["a"]内容还是1 | 1 |
3 | c 2 | c | 2 | 1 | 不是a房间,不进行计算,h["a"]内容还是1 | 1 |
4 | d 7 | d | 7 | 1 | 不是a房间,不进行计算,h["a"]内容还是1 | 1 |
5 | b 5 | b | 5 | 1 | 不是a房间,不进行计算,h["a"]内容还是1 | 1 |
6 | a 3 | a | 3 | 1 | h["a"]=1+3 | 4 |
7 | g 2 | g | 2 | 4 | 不是a房间,不进行计算,h["a"]内容还是1 | 4 |
8 | f 6 | f | 6 | 4 | 不是a房间,不进行计算,h["a"]内容还是1 | 4 |
9 | d 9 | d | 9 | 4 | 不是a房间,不进行计算,h["a"]内容还是1 | 4 |
似曾相识的表格呀,我看结合这个表格看看执行过程。
首先读取第一行:
$1内容是a,$2内容是1,这里我们也创建了数组h[$1],我们要计算h[$1]=h[$1]+$2,即h["a"]=空+1.此时h["a"]的内容是1.
然后读取第二行:
$1内容是b,不是我们要的a房间我们跳过,此时h["a"]的内容依然是1
继续往下读情况都是一样的直到读取到第六行
$1内容是a,$2内容是3,这里我们也创建了数组h[$1],我们要计算h[$1]=h[$1]+$2,即h["a"]=1+4.此时h["a"]的内容是4.
awk继续往下读取直到读取到最后一行$1都不是a,所以h["a"]房间的内容不会发生变化。
现在大家再看一下执行过程,注意我们只关注h["a"]房间的内容。
[root@show awkfile]# awk ‘{h[$1]=h[$1]+$2;print"当前行内容:"$0,"a房间内容:"h["a"]}‘ array_add.txt 当前行内容:a 1 a房间内容:1 当前行内容:b 3 a房间内容:1 当前行内容:c 2 a房间内容:1 当前行内容:d 7 a房间内容:1 当前行内容:b 5 a房间内容:1 当前行内容:a 3 a房间内容:4 当前行内容:g 2 a房间内容:4 当前行内容:f 6 a房间内容:4 当前行内容:d 9 a房间内容:4
这时候你应该理解他到底如何执行的了。
下面我们看看他完整的执行过程。
行号 | 当前行的内容 | $1的内容 | $2的内容 | h[$1]之前的内容 | h[$1]=h[$1]+$2 | h[$1]之后的内容 |
1 | a 1 | a | 1 | 空 | h["a"]=空+1 | 1 |
2 | b 3 | b | 3 | 空 | h["b"]=空+3 | 3 |
3 | c 2 | c | 2 | 空 | h["c"]=空+2 | 2 |
4 | d 7 | d | 7 | 空 | h["d"]=空+7 | 7 |
5 | b 5 | b | 5 | 3 | h["b"]=3+5 | 8 |
6 | a 3 | a | 3 | 1 | h["a"]=1+3 | 4 |
7 | g 2 | g | 2 | 空 | h["g"]=空+2 | 2 |
8 | f 6 | f | 6 | 空 | h["f"]=空+6 | 6 |
9 | d 9 | d | 9 | 7 | h["d"]=7+9 | 16 |
执行过程如下:
[root@show awkfile]# awk ‘{h[$1]=h[$1]+$2;print$1"房间内容:"h a房间内容:1 b房间内容:3 c房间内容:2 d房间内容:7 b房间内容:8 a房间内容:4 g房间内容:2 f房间内容:6 d房间内容:16
第四个里程碑-只显示最终结果
刚开始我们看着执行过程,可以帮助我们理解awk数组。但是我们的目标是获得每个房间的最后的结果。所以还要用END模式对awk数组进行处理。
[root@show awkfile]# awk‘{h[$1]=h[$1]+$2}END{for(pol in h)print pol,h[pol]}‘ array_add.txt a 4 b 8 c 2 d 16 f 6 g 2
这就是我们要的最终结果。
本文出自 “李导的博客” 博客,请务必保留此出处http://lidao.blog.51cto.com/3388056/1914563
老男孩教育每日一题-2017年3月28日-awk累计相加