【问题标题】:Inner join on two text files两个文本文件的内连接
【发布时间】:2022-01-27 20:30:39
【问题描述】:

希望对两个不同的文本文件执行内部连接。基本上我正在寻找与 GNU 连接程序等效的内部连接。这样的事情存在吗?如果没有,awksed 解决方案将是最有帮助的,但我的首选是 Linux 命令。

这是我想要做的一个例子

文件 1:

0|Alien Registration Card LUA|Checklist Update
1|Alien Registration Card LUA|Document App Plan
2|Alien Registration Card LUA|SA Application Nbr
3|Alien Registration Card LUA|tmp_preapp-DOB
0|App - CSCE Certificate LUA|Admit Type
1|App - CSCE Certificate LUA|Alias 1
2|App - CSCE Certificate LUA|Alias 2
3|App - CSCE Certificate LUA|Alias 3
4|App - CSCE Certificate LUA|Alias 4

文件 2:

Alien Registration Card LUA

结果:

0|Alien Registration Card LUA|Checklist Update
1|Alien Registration Card LUA|Document App Plan
2|Alien Registration Card LUA|SA Application Nbr
3|Alien Registration Card LUA|tmp_preapp-DOB

【问题讨论】:

    标签: linux bash join


    【解决方案1】:

    这是一个 awk 选项,因此您可以避免 bash 依赖(为了可移植性):

    $ awk -F'|' 'NR==FNR{check[$0];next} $2 in check' file2 file1
    

    这是如何工作的?

    • -F'|' -- 设置字段分隔符
    • 'NR==FNR{check[$0];next} -- 如果总记录数与文件记录数匹配(即我们正在读取提供的第一个文件),那么我们填充一个数组并继续。
    • $2 in check -- 如果我们创建的数组中提到了第二个字段,则打印该行(如果未提供任何操作,这是默认操作)。
    • file2 file1 -- 文件。由于NR==FNR 构造,顺序很重要。

    【讨论】:

    • 我有一个场景,我有一个东西列表,其中一个重复行其他没有,所以最后,我有两个文件:一个只包含重复行,另一个包含唯一行。因此,当我运行此 awk 时,它会将它们合并为一种魅力。感谢@ghoti,它成功了!
    【解决方案2】:

    file2最后不应该包含LUA吗?

    如果是,你仍然可以使用join

    join -t'|' -12 <(sort -t'|' -k2 file1) file2
    

    【讨论】:

    • 谢谢!是的,它应该(我已经更新了问题)。我不知道有人可以通过标准输入输出并反馈结果。很有用!
    • @DaveSnigier:您始终可以创建一个临时文件,但 Process Substitution 的输入要短得多。
    • 两个输入文件都需要排序,join 才能正常工作。这是一个主要缺点,特别是如果您的文件很大。对许多访问者来说,Awk 解决方案可能会更有用。
    【解决方案3】:

    看起来你只需要

    grep -F -f file2 file1
    

    【讨论】:

    • 需要注意的是,这将找到 substring 匹配项;即,如果带有密钥的文件包含dog,它将在另一个文件中找到包含endogenousdoggone 的行。您可以通过从搜索静态字符串的grep -F 切换到通过正则表达式搜索的普通grep(或grep -E 以获得更通用的正则表达式方言)来解决此问题,但是您必须修改模式文件等,此时此页面上的其他答案可能会不那么复杂且更易于理解。但是,如果您的密钥很长,或者您知道没有意外匹配,则此方法有效。
    • 这在某些情况下是一个很好的补救措施,但在其他情况下则不然,它会阻止一个词匹配另一个词的一部分,但如果您的字段有时可能包含多个词(即“完整" 将匹配 "not full",即使是 -w)。
    【解决方案4】:

    您可以修改此脚本:

    cat file2 | while read line; do
        grep $line file1 # or whatever you want to do with the $line variable
    done
    

    while 循环逐行读取 file2 并将该行提供给 grep 命令,该命令在 file1 中对该行进行 grep。有一些额外的输出可能会被 grep 选项删除。

    【讨论】:

    • 非常聪明!除了这个直接的问题,我将能够找到这种模式的许多用途
    • 别忘了引用$line。如果它包含空格,它可能会被严重扩展。此外,如果您正在寻找固定字符串匹配而不是正则表达式(请记住,它是 gREp),请使用 -F 选项。
    • 这只是@glennjackman 对this anwer 的低效解释。 (是的,他后来发布了。)读取模式然后只检查一次目标文件的单个grep 比为每个模式运行一个grep 效率要高得多,当然对于大量输入而言尤其如此。跨度>
    • @ghoti 的评论措辞可能更强烈。即使您的输入不包含空格,如果输入包含任何 shell 元字符,事情也可能会出错。 TL;DR 此处省略引号是错误
    • @ketil:不需要;只需使用grep -Fx-F = 固定字符串(不是正则表达式),-x = 行匹配)。
    【解决方案5】:

    您可以使用粘贴命令来组合文件:

    paste [option] source files [>destination file]
    

    你的例子是

    paste file1.txt file2.txt >result.txt
    

    【讨论】:

    • 关闭,但粘贴只会加入两个文件的行号。我实际上希望加入文件中的一个字段。
    猜你喜欢
    • 2023-03-03
    • 2018-07-01
    • 2015-09-09
    • 2012-02-03
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    相关资源
    最近更新 更多