【问题标题】:How to pull out all lines of a file matching each line from another file and output into separate rows?如何从另一个文件中提取与每一行匹配的文件的所有行并输出到单独的行中?
【发布时间】:2016-02-06 22:09:00
【问题描述】:

这与之前提出的问题类似(请参阅下面的链接),但这次我想将常用字符串输出到行而不是列中,如下所示:

我有两个文件,每个文件都有一列,如下所示:

文件 1

chr1 106623434
chr1 106623436
chr1 106623442
chr1 106623468
chr1 10699400
chr1 10699405
chr1 10699408
chr1 10699415
chr1 10699426
chr1 10699448
chr1 110611528
chr1 110611550
chr1 110611552
chr1 110611554
chr1 110611560

文件 2

chr1 1066234
chr1 106994
chr1 1106115

我想搜索文件 1 并提取与文件 2 的第 1 行完全匹配的所有行,并在它自己的行上输出所有匹配项。然后我想对文件 2 的第 2 行做同样的事情,依此类推,直到在文件 1 中找到文件 2 的所有匹配项并输出到它自己的行。此外,我正在处理非常大的文件,因此不需要将文件 2 完全存储在内存中,否则它不会运行完成。希望输出看起来像这样:

chr1 106623434  chr1 106623436  chr1 106623442  chr1 106623468
chr1 10699400   chr1 10699405   chr1 10699408   chr1 10699415   chr1 10699426  chr1 10699448 
chr1 110611528  chr1 110611550  chr1 110611552  chr1 110611554  chr1 110611560  

类似的问题: How to move all strings in one file that match the lines of another to columns in an output file?

【问题讨论】:

    标签: awk grep


    【解决方案1】:

    只要你的模式不完全重叠,这应该可以工作

    $ while read p; do grep "$p" file1 | tr '\n' '\t'; echo "";  done < file2
    chr1 106623434  chr1 106623436  chr1 106623442  chr1 106623468
    chr1 10699400   chr1 10699405   chr1 10699408   chr1 10699415   chr1 10699426   chr1 10699448
    chr1 110611528  chr1 110611550  chr1 110611552  chr1 110611554  chr1 110611560
    

    【讨论】:

      【解决方案2】:

      您可以这样做,因为它使用接近于零的内存,但它会非常慢,因为它会为“file2”的每一行读取整个“file1”一次:

      $ cat tst.awk
      {
          ofs = ors = ""
          while ( (getline line < "file1") > 0) {
              if (line ~ "^"$0) {
                  printf "%s%s", ofs, line
                  ofs = "\t"
                  ors = "\n"
              }
          }
          printf ors
          close("file1")
      }
      
      $ awk -f tst.awk file2
      chr1 106623434  chr1 106623436  chr1 106623442  chr1 106623468
      chr1 10699400   chr1 10699405   chr1 10699408   chr1 10699415   chr1 10699426   chr1 10699448
      chr1 110611528  chr1 110611550  chr1 110611552  chr1 110611554  chr1 110611560
      

      【讨论】:

      • 这确实有效,但你是对的,它很慢。感谢您再次这样做。
      【解决方案3】:

      你可以试试

      awk -vOFS="\t" '
      NR==FNR{                      #only file2
          keys[++i]=$0;             #'keys' store pattern to search ('i' contains number of keys)
          next;                     #stop processing the current record and 
                                    #go on to the next record
      }
      {
          for(j=1; j<=i; ++j)
              #if line start with key then add
              if($0 ~ "^"keys[j])
                  a[keys[j]] = a[keys[j]] (a[keys[j]]!=""?OFS:"") $0;
      }
      END{
          for(j=1; j<=i; ++j) print a[keys[j]];  #print formating lines
      }' file2 file1
      

      你明白了,

      chr1 106623434 chr1 106623436 chr1 106623442 chr1 106623468 chr1 10699400 chr1 10699405 chr1 10699408 chr1 10699415 chr1 10699426 chr1 10699448 chr1 110611528 chr1 110611550 chr1 110611552 chr1 110611554 chr1 110611560

      【讨论】:

      • 你能解释一下发生了什么吗?
      • OP 说他需要something that won't require file 2 to be completely stored in memory, otherwise it will not run to completion。否则他之前的问题的解决方案会奏效。
      • @EdMorton 它可以在不消耗太多内存的情况下做到这一点,但对于非常大的文件同样有效(时间和内存),它可以使用多线程吗? ....
      • 击败我,我不知道如何在合理的时间内使用更少的内存。
      猜你喜欢
      • 2021-03-25
      • 2017-04-24
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多