【问题标题】:How to merge two .txt file in unix based on one common column. Unix如何在 unix 中基于一个公共列合并两个 .txt 文件。 Unix
【发布时间】:2021-09-02 19:59:47
【问题描述】:

我有两个 .txt 文件。文件 1.txt 和文件 2.txt。如何在 unix 中基于一个公共列合并这两个文件(可能与 awk 一起使用)。

File1.txt 看起来像

Sub_ID  Sam_ID   v1              
1878372 2253734 SAMN06396112           
1883177 2264293 SAMN06414028          
1884646 2275341 SAMN06432785         
1860945 2277481 SAMN06407597  

File2.txt 看起来像

Sam_ID  code    V3      V4 
2253734 20481   NA      DNA   
2275341 20483   NA      DNA    
2277481 20488   NA      DNA   

合并后的最终输出文件应该是这样的

Finalfile.txt

Sub_ID  Sam_ID   v1               code   V3      V4
1878372 2253734 SAMN06396112     20481   NA      DNA                
1884646 2275341 SAMN06432785     20483   NA      DNA     
1860945 2277481 SAMN06407597     20488   NA      DNA  

到目前为止,我已经尝试过加入,但可能是我没有完全理解该命令(对 unix 来说是新手)。

sort -k2b File1.txt >sorted_file1.txt 
sort File2.txt >sorted_file2.txt 
join -1 2 sorted_file1.txt sorted_file2.txt > Finalfile.txt

我知道,通过 k2b,我指定 File_1 的第二列在两个列之间通用,然后合并。

【问题讨论】:

  • 能否请您向我们展示您的任何尝试?
  • 您可以使用支持关系数据库的编程语言并使用它来创建 SQLite 数据库,然后在两个“表”之间执行连接并生成您想要的输出。
  • 两个文件中的字段分隔符是什么?一个制表符还是多个空格?
  • 一个标签。 @赛勒斯

标签: bash unix join awk merge


【解决方案1】:

这个awk 应该是合并任务的工作文件:

awk 'FNR==NR {map[$2] = $0; next} {print map[$1], $0}' File1.txt File2.txt | column -t

Sub_ID   Sam_ID   v1            Sam_ID   code   V3  V4
1878372  2253734  SAMN06396112  2253734  20481  NA  DNA
1884646  2275341  SAMN06432785  2275341  20483  NA  DNA
1860945  2277481  SAMN06407597  2277481  20488  NA  DNA

column -t 仅用于表格输出。

PS:如果在 File1 中找不到 File2 的第一列,那么您将在输出中获得前导空格。

【讨论】:

    【解决方案2】:

    使用 cut greppr 以及来自 bash 的 ProcSub。

    pr -mt <(grep -Fv 1883177 file1.txt) <(cut -d' ' -f2- file2.txt)
    

    输出

    Sub_ID  Sam_ID   v1                  code    V3      V4
    1878372 2253734 SAMN06396112        20481   NA      DNA
    1884646 2275341 SAMN06432785        20483   NA      DNA
    1860945 2277481 SAMN06407597        20488   NA      DNA
    

    paste

    paste -d' ' <(grep -Fv 1883177 file1.txt) <(cut -d' ' -f2- file2.txt) | column -t > Finalfile.txt
    

    【讨论】:

      【解决方案3】:

      感谢您添加自己的尝试来解决问题 - 它使故障排除变得更加容易。

      这个答案有点复杂,但这里有一个潜在的解决方案(GNU 加入):

      join -t $'\t' -1 2 -2 1 <(head -n 1 File1.txt && tail -n +2 File1.txt | sort -k2,2 ) <(head -n 1 File2.txt && tail -n +2 File2.txt | sort -k1,1)
      
      #Sam_ID Sub_ID  v1  code    V3  V4
      #2253734    1878372 SAMN06396112    20481   NA  DNA
      #2275341    1884646 SAMN06432785    20483   NA  DNA
      #2277481    1860945 SAMN06407597    20488   NA  DNA
      

      解释:

      • join 使用单个字符作为分隔符,所以不能使用"\t",但可以使用$'\t'(据我所知)
      • -1 2-2 1 在合并文件时表示“对于第一个文件,使用第二个字段”和“对于第二个文件,使用第一个字段”
      • 在每个子进程 (&lt;()) 中,按 Sam_ID 列对文件进行排序,但从排序中排除标题(根据 Is there a way to ignore header lines in a UNIX sort?

      编辑

      要指定输出中列的顺序(将 Sub_ID 放在 Sam_ID 之前),您可以使用 -o 选项,例如

      join -t $'\t' -1 2 -2 1 -o 1.1,1.2,1.3,2.2,2.3,2.4 <(head -n 1 File1.txt && tail -n +2 File1.txt | sort -k2,2 ) <(head -n 1 File2.txt && tail -n +2 File2.txt | sort -k1,1)
      
      #Sub_ID Sam_ID  v1  code    V3  V4
      #1878372    2253734 SAMN06396112    20481   NA  DNA
      #1884646    2275341 SAMN06432785    20483   NA  DNA
      #1860945    2277481 SAMN06407597    20488   NA  DNA
      

      【讨论】:

      • 嗨 Jared:谢谢,但我在尝试时面临的唯一问题是标题被删除。有没有办法避免这种情况?
      • 在我的示例中,每个文件的标题都被保留。您确定它们被一个标签分隔吗?
      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-12
      • 1970-01-01
      相关资源
      最近更新 更多