84669 orang belajar
152542 orang belajar
20005 orang belajar
5487 orang belajar
7821 orang belajar
359900 orang belajar
3350 orang belajar
180660 orang belajar
48569 orang belajar
18603 orang belajar
40936 orang belajar
1549 orang belajar
1183 orang belajar
32909 orang belajar
用 shell 处理一个文本文件,内容如下:
fdf 284 asd 112 adf 146 csb 513 dfg 576 asd 346 adf 263 csb 092 dfg 547
根据第一列去重,相同的保留第二列值最大的那个,结果数据应该是这样的:
fdf 284 asd 346 adf 263 csb 513 dfg 576
看了下 uniq 命令,好像不支持按字段去重。请问该如何去重呢?
学习是最好的投资!
方法一
cat data.txt | sort -rnk2 | awk '{if (!keys[$1]) print $0; keys[$1] = 1;}'
先按照第二列逆序排列,保证数字从大到小输出,然后再用 awk,只有第一列的字符串第一次出现才输出这个字符串,其他的丢弃,这样应该就可以解决问题了。但是这种方法可能会让 awk 占用很多的内存,文件过大的话有问题。
方法二
cat data.txt | sort -k1,1 | awk '{ if (lastKey == $1) { if (lastValue < $2) { lastLine = $0; lastValue = int($2); } } else { if (lastLine) { print lastLine; } lastKey = $1; lastLine = $0; lastValue = int($2); } } END { if (lastLine) { print lastLine; } }'
这个方案是按照第一列排序,然后用 awk 筛选结果,筛选的过程相当于一个加强版的 uniq。这个方案在内存使用方面好了很多,不过代码量略多,不是很简洁。
$ sort -r a.txt | awk '{print $2, $1}' | uniq -f1 | awk '{print $2, $1}' fdf 284 dfg 576 csb 513 asd 346 adf 263
逆排, 反转第一列和第二列, 按第二列去重, 反转第一列和第二列
awk 'BEGIN{ a[$1]=$2 }{ if ($2>a[$1] ) a[$1]=$2 }END{for (i in a) if (i) print i,a[i]}' data.txt
把第一列放入数组 然后对比数组的值 大的就替换掉为新的值
[root@localhost ~]# sort -k2r 1.txt|awk '!a[$1]++' dfg 576 csb 513 asd 346 fdf 284 adf 263
方法一
先按照第二列逆序排列,保证数字从大到小输出,然后再用 awk,只有第一列的字符串第一次出现才输出这个字符串,其他的丢弃,这样应该就可以解决问题了。但是这种方法可能会让 awk 占用很多的内存,文件过大的话有问题。
方法二
这个方案是按照第一列排序,然后用 awk 筛选结果,筛选的过程相当于一个加强版的 uniq。这个方案在内存使用方面好了很多,不过代码量略多,不是很简洁。
逆排, 反转第一列和第二列, 按第二列去重, 反转第一列和第二列
把第一列放入数组 然后对比数组的值 大的就替换掉为新的值