【问题标题】:Compare Two Files with duplicate input value比较具有重复输入值的两个文件
【发布时间】:2019-09-08 16:54:24
【问题描述】:

我有以下两个文件

BC.txt

"PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
"PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;

PB.txt

c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10";
c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10";
c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10";
c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10";

我正在尝试将 BC.txt 的 Col1 与 PB.txt 的 Col12 进行比较,并将匹配项彼此相邻打印。对于 BC.txt 的 col1 中的相同值,在 col2 和 Col3 中具有不同的值。因此,在比较时,我只得到 BC.txt 的一个条目的输出。但我想要所有人。

    awk 'BEGIN {OFS=FS} NR==FNR {a[$1]=($2" "$3);next} $12 in a {print $0,a[$12]}' BC.txt PB.txt

预期输出

c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;

我想将 BC.txt 的所有条目与 PB.txt 的条目进行比较;但由于它的值相同,我的代码无法正常工作。

【问题讨论】:

    标签: for-loop if-statement awk


    【解决方案1】:

    如果您不关心与问题中预期输出相比的输出行顺序,则将 BC.txt 读入内存,因为它更简洁:

    $ cat tst.awk
    NR==FNR {
        map[$1,++cnt[$1]] = $2 OFS $3
        next
    }
    {
        for (c=1; c<=cnt[$12]; c++) {
            print $0, map[$12,c]
        }
    }
    
    $ awk -f tst.awk BC.txt PB.txt
    c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    

    但如果你在乎的话:

    $ cat tst.awk
    NR==FNR {
        map[$12,++cnt[$12]] = $0
        next
    }
    {
        for (c=1; c<=cnt[$1]; c++) {
            print map[$1,c], $2, $3
        }
    }
    
    $ awk -f tst.awk PB.txt BC.txt
    c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AGCGGCCT; BC=TTTCAGCGCCGA;
    c4  PB  tr  41258945    41270445    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41258945    41259026    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41259626    41259754    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    c4  PB  Ex  41262664    41262814    .   +   .   g_i "PB.50262"; t_i "PB.50262.10"; UMI=AAGCGGCC; BC=TTTCAGCGCCGA;
    

    【讨论】:

      【解决方案2】:

      您可以使用join 来执行此操作吗? (如果列已排序,或 sort。

      $ join BC.txt <(awk '{print $12,$0}' PB.txt) | cut -d' ' -f 4-
      c4 PB tr 41258945 41270445 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41258945 41259026 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41259626 41259754 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41262664 41262814 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB tr 41258945 41270445 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41258945 41259026 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41259626 41259754 . + . g_i "PB.50262"; t_i "PB.50262.10";
      c4 PB Ex 41262664 41262814 . + . g_i "PB.50262"; t_i "PB.50262.10";
      

      并剪切/awk 想要退出连接的列?

      【讨论】:

      • 您还需要为每个文件添加“排序”,因为连接需要排序输入。加入也是我的第一个想法,但是当您需要对输入进行排序然后通过管道传输到 awk 以选择/重新排序字段时,这似乎不是正确的方法。也许是吧,idk。
      • 我认为对于小文件,awk 两次传递是一种享受。我习惯了生物信息学文件,我们从来没有足够的内存来存储任何东西。
      • @dr-who 加入很棒而且很有帮助;但是因为我需要对文件进行排序,所以我丢失了订单(这有时很重要)。所以,我一直在寻找 awk 解决方案。
      【解决方案3】:

      您能否尝试以下操作(仅使用您提供的样本进行测试)。

      awk '
      FNR==NR{
        a[++count]=$0
        b[count]=$12
        next
      }
      {
        for(i=1;i<=count;i++){
          split(a[i],array," ")
          if($1==array[12]){
             print a[i],$2,$3
          }
        }
      }'  PB.txt BC.txt
      

      说明:现在为上述代码添加说明。

      awk '                         ##Starting awk program here.
      FNR==NR{                      ##Checking condition FNR==NR which will be TRUE when PB.txt is being read.
        a[++count]=$0               ##Creating an array named a whose index is variable count with incrment value of 1 and value is current line.
        b[count]=$12                ##Creating an array named b whose  index is variabe count and value if 12th column.
        next                        ##next will skip all further statements from here.
      }
      {
        for(i=1;i<=count;i++){      ##Starting a for loop from here from i=1 to till value of count.
          split(a[i],array," ")     ##Splitting value of a[i] into array named array whose delimiter is space.
          if($1==array[12]){        ##Checking condition if $1 is equal to array[12] then do following.
             print a[i],$2,$3       ##Printing array a value along with 2nd and 3rd column value.
          }
        }
      }'  PB.txt BC.txt             ##Mentioning Input_files names here.
      

      【讨论】:

      • 我的两个文件都很大。它仍在运行。但初始输出表明它可以按我的意愿完美运行。
      • 它们有多大?是的,因为每行都在运行一个循环,所以这需要时间。我不认为文件很大,因此经过测试并使用提供的示例创建了它。如果有任何疑问,请发帖,我会在早上回答,这里已经很晚了:)
      • 这将非常慢,因为对于 BC.txt 的每一行,它都会遍历 PB.txt 的每一行,并在 PB.txt 的那一行上再次进行字段拆分。另外 - 我没有看到 b[] 在初始化后被使用。
      猜你喜欢
      • 1970-01-01
      • 2021-03-01
      • 2023-04-02
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 2018-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多