Linux 中如何找到 2 个文件的并集 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
kkyypy
V2EX    Linux

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

  •  1
     
  •   kkyypy 2022-12-07 15:54:36 +08:00 3303 次点击
    这是一个创建于 1039 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题有一个文件 a ,只有一列存着 id
    文件 b 是 3 列,存着 id 和其他字段
    想找到文件 b 中 id 为文件 a 中的 id 的所有行

    大佬们除了遍历还有什么其他的方法吗,因为文件 b 的行数大概有 2 亿。。。哭死
    29 条回复    2022-12-08 17:57:59 +08:00
    macy
        1
    macy  
       2022-12-07 16:00:32 +08:00
    没想到啥好办法,遍历是肯定的,如果后面长期查找,可以尝试把文件存到数据库里吧
    Shinoda
        2
    Shinoda  
       2022-12-07 16:03:35 +08:00
    可以用用 command line 试试? 比如 grep -Fwf a.txt b.txt 之类的? 假设你只有 a.txt 只有 id
    dqzcwxb
        3
    dqzcwxb  
       2022-12-07 16:07:44 +08:00
    读到内存改成 map 优化成 O(1)去匹配,内存不够就读一半还不够就再分一半用分治法解决
    chaleaochexist
        4
    chaleaochexist  
       2022-12-07 16:12:24 +08:00
    好像有个布隆过滤器 精度要求不高的情况下可以考虑. redis 就支持.
    xiaolinjia
        5
    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
        6
    kkyypy  
    OP
       2022-12-07 16:29:56 +08:00
    @macy 主要是上游业务方推过来的,而且这个文件是 leader 指定要用的就很迷茫,更新是上游更新的,我很难推动啊。。。
    kkyypy
        7
    kkyypy  
    OP
       2022-12-07 16:31:14 +08:00
    @Shinoda 感谢老哥 这个占用资源少多了
    @xiaolinjia 哈哈 牛皮
    @dqzcwxb 感谢回复 我试一下
    @chaleaochexist 感谢回复~
    rekulas
        8
    rekulas  
       2022-12-07 16:33:22 +08:00
    遍历是必须的,毕竟总得访问才能对比,就算用工具内部也是遍历。。

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

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


    @winglight2016 就 2 亿数据,感觉一个几百 KB 的 SQLite 都能很好应对,不必要上大数据平台吧
    TimePPT
        11
    TimePPT  
    PRO
       2022-12-07 18:02:50 +08:00
    啥文件?量大可以导入数据库,量小,除了 LS 的办法,如果类 csv ,可以试试 csvq https://github.com/mithrandie/csvq
    zthxxx
        12
    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
        13
    littlewing  
       2022-12-07 18:59:47 +08:00
    导入数据库
    garyox64
        14
    garyox64  
       2022-12-07 21:36:47 +08:00   2
    grep 就支持,就是 chatgpt 回答的用法,具体选项可以自己再研究下
    看来这个 chatgpt 有点厉害啊,我得去研究下
    Tanix2
        15
    Tanix2  
       2022-12-07 21:46:11 +08:00
    没有其他假设的话,b 文件肯定要遍历,如果有一行没遍历,该行 id 可能在 a 中,这就少算了一个结果了。
    如果 b 中 id 是有规律的,比如有序,那么可以不遍历,比如可以二分查找。
    Tanix2
        16
    Tanix2  
       2022-12-07 21:49:42 +08:00
    这个是交集,因为你要求的是 a 、b 共有的。
    lululau
        17
    lululau  
       2022-12-07 22:06:26 +08:00
    grep -Ff a.txt b.txt # 前提是 ID 列的值不会碰巧被包含在其他列中

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

    如果分隔符不是空格或者需要匹配的字段不是第一个,man join 自己查。
    julyclyde
        22
    julyclyde  
       2022-12-08 08:36:50 +08:00
    comm 命令
    要加参数
    libook
        23
    libook  
       2022-12-08 10:11:27 +08:00
    拿 Python 之类的写个脚本实现吧,用 shell 调用执行,shell 自己处理这种 case 可能十分吃力,毕竟 shell 只是个用来启动其他程序的工具。
    jurassic2long
        24
    jurassic2long  
       2022-12-08 10:30:31 +08:00
    还是上数据库吧,sqlite 就行,免去了各种细节问题,操作简单,计算高效
    wxf666
        25
    wxf666  
       2022-12-08 11:05:26 +08:00
    @ruidoBlanco @julyclyde `join` 和 `comm` 命令都要求 a.txt 和 b.txt 排好序了吧。。

    如果俩文件都排好序了的话,反而没必要遍历 b.txt 了。如 @Tanix2 #16 所说,用二分查找更快
    sparkssssssss
        26
    sparkssssssss  
       2022-12-08 11:46:18 +08:00
    假定 a 的第一列是 id, b 的第一列也是 id,如果不是,修改以下 $1,如果 b 的 id 不固定,则忽略这个回答.

    awk 'NR==FNR {a[$1];next} $1 in a' a b
    xyjincan
        27
    xyjincan  
       2022-12-08 12:50:03 +08:00
    A 文件进内存,B 文件逐行输出,程序也许一分钟就跑完了
    julyclyde
        28
    julyclyde  
       2022-12-08 14:37:40 +08:00
    @wxf666 是的要求排序。
    lizuoqiang
        29
    lizuoqiang  
       2022-12-08 17:57:59 +08:00
    join -t , a.txt b.txt
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5192 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 09:26 PVG 17:26 LAX 02:26 JFK 05:26
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86