Keuin 最近的时间轴更新
Keuin

Keuin

V2EX 第 211862 号会员,加入于 2017-01-22 19:01:13 +08:00
Keuin 最近回复了
@wxf666 自己研究一下吧,昨天的楼被删了,我懒得再写一遍了,只需要假定 csv 列数固定,不需要用到 cut 。如果假定不了,简便起见,需要找一个输入里面没有的分隔符。
写入量的话,我在原 po 主帖子里分析过,不过那里把加行号的中间结果也全部存下来了,所以当时给的磁盘用量是 3*6TB 。如果都用流式传递中间结果的话,两个 sort 需要有 2*6TB 的临时空间。
@wxf666 昨天写的马虎,忘记顺序这个要求了,我其实又回复了一次来 update ,不过看起来楼被 v 站吞了。保序的方案是用 sort -u -k1,4 来只按原内容排序并去重,最后 sed 去掉行号,最最后的 uniq 去掉即可
@Keuin 没有保序,bugfix 一下。假设 csv 有 4 列,把 sort 替换成`sort -u -t, -k1,4 | sort -t, -k5`,把结尾的 uniq 删掉,变成:

```shell
awk '{print $0","NR}' input | sort -u -t, -k1,4 | sort -t, -k5 | sed -E 's/,[0-9]+$//' | uniq
```
不能假设列数的话,受这几个 shell 工具的限制,需要换一个没有出现过的字符做分隔符
```shell
awk '{print $0","NR}' input.csv | sort | sed -E 's/,[0-9]+$//' | uniq
```

Example usage:

```
$ cat input
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,7
2,3,4,5
1,2,3,4
5,6,7,8
$ awk '{print $0","NR}' input
1,2,3,4,1
2,3,4,5,2
3,4,5,6,3
4,5,6,7,4
2,3,4,5,5
1,2,3,4,6
5,6,7,8,7
$ awk '{print $0","NR}' input | sort
1,2,3,4,1
1,2,3,4,6
2,3,4,5,2
2,3,4,5,5
3,4,5,6,3
4,5,6,7,4
5,6,7,8,7
$ awk '{print $0","NR}' input | sort | sed -E 's/,[0-9]+$//'
1,2,3,4
1,2,3,4
2,3,4,5
2,3,4,5
3,4,5,6
4,5,6,7
5,6,7,8
$ awk '{print $0","NR}' input | sort | sed -E 's/,[0-9]+$//' | uniq
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,7
5,6,7,8
```

不管你的电脑内存是 1T 还是 1G ,都可以正确运行并得到相同输出,因为 sort 命令用的是归并排序,是外存算法。如果你要限制用到的内存大小,把 sort 改成 sort --buffer-size=100M ,即可限制只用 100M 内存,其他命令都是行缓存算法,只会保存当前行在内存里,也就是说,最大内存用量是 max(100M, max_line_size_bytes)
一行 shell 的事被你搞得这么复杂,6TB 可以存内存里,6PB 呢?
看不下去了,这个源码也不愿意给,我直接给出结论:
```shell
awk '{print $0","NR}' input.csv | sort | sed -E 's/,[0-9]+$//' | uniq
```
其中 input.csv 替换成你的输入文件,结果将出现在 stdout ,如果要存到文件,自己重定向一下即可。
运行实例:
```
$ cat input
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,7
2,3,4,5
1,2,3,4
5,6,7,8
$ awk '{print $0","NR}' input
1,2,3,4,1
2,3,4,5,2
3,4,5,6,3
4,5,6,7,4
2,3,4,5,5
1,2,3,4,6
5,6,7,8,7
$ awk '{print $0","NR}' input | sort
1,2,3,4,1
1,2,3,4,6
2,3,4,5,2
2,3,4,5,5
3,4,5,6,3
4,5,6,7,4
5,6,7,8,7
$ awk '{print $0","NR}' input | sort | sed -E 's/,[0-9]+$//'
1,2,3,4
1,2,3,4
2,3,4,5
2,3,4,5
3,4,5,6
4,5,6,7
5,6,7,8
$ awk '{print $0","NR}' input | sort | sed -E 's/,[0-9]+$//' | uniq
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,7
5,6,7,8
```

不管你的电脑内存是 1T 还是 1G ,都可以正确运行并得到相同输出,因为 sort 命令用的是归并排序,是外存算法。如果你要限制用到的内存大小,把 sort 改成 sort --buffer-size=100M ,即可限制只用 100M 内存,其他命令都是行缓存算法,只会保存当前行在内存里,也就是说,最大内存用量是 max(100M, max_line_size_bytes)
@Keuin 最后还差一步,按行号升序排序,重新排序回原来的顺序,最大额外磁盘空间不变
awk 每行尾追加逗号和行号,整个文件每个行都追加一下,占 6.2T
unix sort 工具外排序,直接按字母表排序,占 6.2T 。重复行会变成相邻的,编号不一样。输出另占 6.2T
用 awk 配合 uniq ,去重,全内存 O(1)空间算法,输出占 6.2T ,即为最终结果

中间文件可以在不用的时候删掉,最大同时出现 2 份,也就是需要额外 2*6.2T 磁盘空间,由于都是流式算法,内存用量为很小的常数
88 天前
回复了 abcfreedom 创建的主题 旅行 走错机场,损失惨重,心态有点崩
花钱买教训吧,下次做好 double check ,这种地址信息我一般都是比对文字确认的,两个 app 或者网页的截图来回对照看两三遍,类似于铁路的指差确认。因为人脑具有模糊性,人犯迷糊的时候,就容易稀里糊涂认为是正确的,必须落到文字上,这样就不会出错了。不过更简单的办法是把行程信息发到家庭群里,让家人也帮忙看看,还能减轻自己全程规划的负担,家人也更有参与感
虚拟机装 docker 呗,反正 wsl2 也是虚拟机,不如 hyperv 开个 debian 实例
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1172 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 12ms · UTC 18:27 · PVG 02:27 · LAX 11:27 · JFK 14:27
Developed with CodeLauncher
♥ Do have faith in what you're doing.