linux 如何根据多列去重

2016-12-26 14:00:41 +08:00
 Martin9

采用 awk '!x[$0]++' filename 只能去除完全相同的重复值, awk '!x[$1]++' filename 只能根据第一列的值去重。

现在想要根据多列的数据去重,何解?

(不能借助数据库,或者还有其他的命令能解决?

5479 次点击
所在节点    Linux
12 条回复
knightdf
2016-12-26 15:03:36 +08:00
把这几列拼成字符串再去重不就行了?
imn1
2016-12-26 15:08:13 +08:00
csvtool 辅助
Martin9
2016-12-26 15:49:06 +08:00
@knightdf 那还有其他列的数据要搞,而且这个列位置不能变的
swulling
2016-12-26 15:51:39 +08:00
awk '!x[$0","$1","$3]++',思路要广
Martin9
2016-12-26 16:07:57 +08:00
@imn1 服务器端能用么
Martin9
2016-12-26 16:10:01 +08:00
@swulling 这个是根据第一列和第三列去重么?
我之前用过 awk '!x[$1,$3]++' 去重后条数对不上
imn1
2016-12-26 16:16:54 +08:00
@Martin9
csvtool 是命令行,不过它还是要和其他命令结合用,本身并不算强大

其实处理多列文本如 csv ,还没有什么强大的 cli 工具,我更多用自写 python 处理
swulling
2016-12-26 16:53:36 +08:00
@Martin9 是 $1","$3 ,不是 $1,$3 ,前者是拼接
xss
2016-12-26 17:04:26 +08:00
step 0 : 将要去重的列拼接成一个字符串然后算一个 hash(以 md5 为例, 只要保证位数固定就行)得到列 A
step 1 : 将列 A 当做第一列, 原始日志当做剩余的列输出
step 2 : uniq 有一个参数
-w, --check-chars=N 对每行第 N 个字符以后的内容不作对照

所以, uniq -w32 列 A 为第一列的日志.log

即可完成多列去重.

例子命令(a.log 中, 根据第一列和第三列去重):
```
user@host [16:58:30] : ~
>> cat a.log | awk '{cmd="echo -ne " $1$3"|md5sum -";cmd|getline result;print result"\t"$0}'|sort|uniq -w32 -c
1 7b19de6d4d54999531beb27f758f71f6 - 111 222 333 444
1 c17ed7d7e2d8a60c78c715e165fe3c38 - 111 888 444 666
2 ec1e7077d02cb3dbd61ab73018c4a319 - 111 666 333 777
user@host [16:58:49] : ~
>> cat a.log
111 222 333 444
222 333 444 555
111 666 333 777
111 888 444 666
```
knightdf
2016-12-26 18:19:14 +08:00
@Martin9 大哥,你知道联合主键这个词么?
Martin9
2016-12-26 18:37:49 +08:00
@knightdf 恩这两列在数据库是联合主键,所以 load 到数据库前要去重
Ginson
2016-12-26 18:47:47 +08:00
好不容易看到个我能答的,被抢先了,哭…

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/330225

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX