背景
虽然经常用linux命令,但都是自己平常知道的,也是经常用的最简单的那几个,难度系数不高。几乎每天都在重复的那种,对于一个经常是用linux系统的人来说,永远是德雷福斯模型中的:高手中的新手。有必要每天刺激自己,技术人员的10000小时的弦要紧绷。
试水
早上去看了一下,遇到一个看似简单,但动手去做的时候,还是思考了一下,如果这是面试官提出来的话,短时间不能给出思路跟结论的话,估计就over了。
题目如下:
某个目录下有两个文件a.txt和b.txt,文件格式为(ip,username),
列如:
a.txt
127.0.0.1 zhangsan
127.0.0.1 wangxiaoer
127.0.0.2 lisi
127.0.0.3 wangwu
b.txt
127.0.0.4 lixiaolu
127.0.0.1 lisi
每个文件至少100万行,请使用Linux命令完成如下工作:
1)每个文件各自的ip数
2)出现在b.txt而没有出现在a.txt的ip
3)每个user出现的次数以及每个user对应的ip数
对于1),每个文件各自的IP数据,实质是统计每个文件确切的行数。因为每个文件的每行都是ip&username。所以直接统计行数就OK了。
cat a.txt | wc -l
cat b.txt | wc -l
对于2)出现在b.txt而没有出现在a.txt中的IP。第一反应就是分割出IP列后,使用diff命令去差分,但仔细一想,这不符合要求,因为差分出来的,是形如下面的这种
0a1
> 127.0.0.4
2,4d2
< 127.0.0.1
< 127.0.0.2
< 127.0.0.3
不是真正需要的,虽然也能看出来b.txt中仅有的IP。但还是不方便。最后调查了一下,comm命令就可以很方便的解决这个问题。
思路如下:
1.分别过滤出IP列表。
2.使用comm命令过滤出只有b.txt有的IP
但有一点需要注意,comm差分的文件,是需要拍过序的,否则会出警告。
#comm: file 1/2 is not in sorted order
命令如下
cat a.txt | cut -d' ' -f1 | sort > a_s.txt
cat b.txt | cut -d' ' -f1 | sort > b_s.txt
comm -23 a_s.txt b_s.txt
出力结果如下:
[root@rhel65 temp]# comm -23 b_s.txt a_s.txt
127.0.0.4
这里需要特别的注意一下,comm - 23 只显示在第一个文件中出现而未在第二个文件中出现的行;所以需要将b.txt临时处理文件放置在第一个位置。
对于3),需要对应2个要求,每个user出现的次数;每个user对应的ip数;
使用awk比较方便,直接统计第2个域里面的,每个都存成数据,个数就是数据的个数,这样就可以实现要求了。
awk '{arr1[$1]++;arr2[$2]++;}END {for(i in arr2) {print i, arr1[i],arr2[i] }}' b.txt a.txt
出力如下:
[root@rhel65 temp]# awk '{arr1[$1]++;arr2[$2]++;}END {for(i in arr2) {print i, arr1[i],arr2[i] }}' b.txt a.txt
zhangsan 1
wangxiaoer 1
lisi 2
wangwu 1
lixiaolu 1
或者将2个文件合成一个临时文件
cat a.txt >> tmp
cat b.txt >> tmp
cat tmp | awk '{print $2}' | sort | uniq -c
出力结果如下:
[root@rhel65 temp]# cat tmp | awk '{print $2}' | sort | uniq -c
2 lisi
1 lixiaolu
1 wangwu
1 wangxiaoer
1 zhangsan
user对应的ip数,当出现重复行的时候,就需要去重去统计了,否则就会多算了。
思路,先去重,后统计
cat tmp | uniq -i | awk '{print $2}' | sort | uniq -c
出力如下所示:
[root@rhel65 temp]# cat tmp | uniq -i | awk '{print $2}' | sort | uniq -c
2 lisi
1 lixiaolu
1 wangwu
1 wangxiaoer
1 zhangsan
反思
永远不要做行动的矮子,光说不练假把式。
通用的思路大家都有,就看执行力了,技术还是要慢慢去沉淀。。。。
---over---