Linux 中如何找到 2 个文件的并集

2022-12-07 15:54:36 +08:00
 kkyypy
如题有一个文件 a ,只有一列存着 id
文件 b 是 3 列,存着 id 和其他字段
想找到文件 b 中 id 为文件 a 中的 id 的所有行

大佬们除了遍历还有什么其他的方法吗,因为文件 b 的行数大概有 2 亿。。。哭死
2895 次点击
所在节点    Linux
29 条回复
macy
2022-12-07 16:00:32 +08:00
没想到啥好办法,遍历是肯定的,如果后面长期查找,可以尝试把文件存到数据库里吧
Shinoda
2022-12-07 16:03:35 +08:00
可以用用 command line 试试? 比如 grep -Fwf a.txt b.txt 之类的? 假设你只有 a.txt 只有 id
dqzcwxb
2022-12-07 16:07:44 +08:00
读到内存改成 map 优化成 O(1)去匹配,内存不够就读一半还不够就再分一半用分治法解决
chaleaochexist
2022-12-07 16:12:24 +08:00
好像有个布隆过滤器 精度要求不高的情况下可以考虑. redis 就支持.
xiaolinjia
2022-12-07 16:18:27 +08:00
问了下 chatgpt 。

可以使用 Linux 的 grep 命令来找到两个文件的并集。

假设文件 a 的内容如下:

1
2
3
4

文件 b 的内容如下:

1,foo,bar
2,hello,world
5,foo,baz
6,hello,world

要找到文件 b 中 id 为文件 a 中的 id 的所有行,可以使用以下命令:


grep -f a b
这将输出文件 b 中与文件 a 中的 id 匹配的行,即:


1,foo,bar
2,hello,world
上面的命令中,-f 选项告诉 grep 使用文件 a 作为搜索模式。您可以使用 -w 选项来仅匹配整个单词,而不是部分单词。

例如,如果文件 a 的内容如下:

hello
world
那么使用 -w 选项的命令将输出:

2,hello,world
6,hello,world
但是,如果不使用 -w 选项,命令将输出所有包含文件 a 中的单词的行,即:


1,foo,bar
2,hello,world
5,foo,baz
6,hello,world
因此,要根据需要使用 -w 选项。
kkyypy
2022-12-07 16:29:56 +08:00
@macy 主要是上游业务方推过来的,而且这个文件是 leader 指定要用的就很迷茫,更新是上游更新的,我很难推动啊。。。
kkyypy
2022-12-07 16:31:14 +08:00
@Shinoda 感谢老哥 这个占用资源少多了
@xiaolinjia 哈哈 牛皮
@dqzcwxb 感谢回复 我试一下
@chaleaochexist 感谢回复~
rekulas
2022-12-07 16:33:22 +08:00
遍历是必须的,毕竟总得访问才能对比,就算用工具内部也是遍历。。

awk 实现比较方便
winglight2016
2022-12-07 17:06:45 +08:00
命令行能处理这么大的文件?如果是长期任务,可以考虑用 spark ,也就几行代码
wxf666
2022-12-07 17:21:34 +08:00
俩文件有多大呢?

文件 a 较小的话(内存存得下),如 8 楼所说,一两行 awk 应该就行了


@winglight2016 就 2 亿数据,感觉一个几百 KB 的 SQLite 都能很好应对,不必要上大数据平台吧
TimePPT
2022-12-07 18:02:50 +08:00
啥文件?量大可以导入数据库,量小,除了 LS 的办法,如果类 csv ,可以试试 csvq https://github.com/mithrandie/csvq
zthxxx
2022-12-07 18:08:05 +08:00
假设有一个名为 `file_a.txt` 的文件,包含一列 id ,另一个名为 `file_b.txt` 的文件包含 3 列,第一列为 id ,可以使用以下命令找到 `file_b.txt` 中 id 为 `file_a.txt` 中的 id 的所有行:

```
grep -f file_a.txt file_b.txt
```

这将在 `file_b.txt` 中搜索与 `file_a.txt` 中的 id 匹配的行,并输出这些行。
littlewing
2022-12-07 18:59:47 +08:00
导入数据库
garyox64
2022-12-07 21:36:47 +08:00
grep 就支持,就是 chatgpt 回答的用法,具体选项可以自己再研究下
看来这个 chatgpt 有点厉害啊,我得去研究下
Tanix2
2022-12-07 21:46:11 +08:00
没有其他假设的话,b 文件肯定要遍历,如果有一行没遍历,该行 id 可能在 a 中,这就少算了一个结果了。
如果 b 中 id 是有规律的,比如有序,那么可以不遍历,比如可以二分查找。
Tanix2
2022-12-07 21:49:42 +08:00
这个是交集,因为你要求的是 a 、b 共有的。
lululau
2022-12-07 22:06:26 +08:00
grep -Ff a.txt b.txt # 前提是 ID 列的值不会碰巧被包含在其他列中

不遍历的话,估计这个需求只有上帝能做了
lance6716
2022-12-07 23:28:29 +08:00
手撸一个 SQL join 算子,很有前途
lightjiao
2022-12-08 00:14:06 +08:00
多线程排序遍历( doge )
xiadong1994
2022-12-08 03:33:58 +08:00
ID 的长度是多少?文件 b 的每一行有多长? 2 亿行不算什么大的数据量。

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

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

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

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

© 2021 V2EX