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

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

  •  1
     
  •   kkyypy · 106 天前 · 2378 次点击
    这是一个创建于 106 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题有一个文件 a ,只有一列存着 id
    文件 b 是 3 列,存着 id 和其他字段
    想找到文件 b 中 id 为文件 a 中的 id 的所有行

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

    awk 实现比较方便
    winglight2016
        9
    winglight2016  
       106 天前
    命令行能处理这么大的文件?如果是长期任务,可以考虑用 spark ,也就几行代码
    wxf666
        10
    wxf666  
       106 天前
    俩文件有多大呢?

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


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

    不遍历的话,估计这个需求只有上帝能做了
    lance6716
        18
    lance6716  
       105 天前 via Android
    手撸一个 SQL join 算子,很有前途
    lightjiao
        19
    lightjiao  
       105 天前
    多线程排序遍历( doge )
    xiadong1994
        20
    xiadong1994  
       105 天前
    ID 的长度是多少?文件 b 的每一行有多长? 2 亿行不算什么大的数据量。
    ruidoBlanco
        21
    ruidoBlanco  
       105 天前
    join a.txt b.txt

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

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

    awk 'NR==FNR {a[$1];next} $1 in a' a b
    xyjincan
        27
    xyjincan  
       105 天前
    A 文件进内存,B 文件逐行输出,程序也许一分钟就跑完了
    julyclyde
        28
    julyclyde  
       105 天前
    @wxf666 是的要求排序。
    lizuoqiang
        29
    lizuoqiang  
       105 天前
    join -t , a.txt b.txt
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   2856 人在线   最高记录 5556   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 14:08 · PVG 22:08 · LAX 07:08 · JFK 10:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.