Remover linha no Arquivo A se a linha no Arquivo B corresponder a várias colunas no Arquivo A

1

esta é a minha primeira pergunta neste site, então, por favor, desculpe se eu não explicar isso bem. Eu sou um novato também. Eu estudei algumas coisas de linha de comando em perl e unix, mas não consigo descobrir como resolver isso.

Eu tenho 2 arquivos - Arquivo A, que é o arquivo mestre com mais de 10 colunas e aproximadamente 15.000 linhas, e Arquivo B, que contém 4 colunas e cerca de 1.500 linhas.

Eu quero pegar cada linha de cada vez no Arquivo B, e combinar essas colunas com as colunas correspondentes no Arquivo A (elas não estão na mesma ordem entre os dois arquivos, mas os cabeçalhos das colunas são os mesmos). Se houver uma correspondência em todas as 4 colunas do Arquivo B no Arquivo A, remova toda a linha do Arquivo A e coloque em um novo arquivo (Arquivo C).

Exemplo:

Arquivo A

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 4   57497067    na  no  612 612 DonorAR2
54  Baillie2011 X   154790187   TMLHE   no  612 612 DonorAR2
54  Baillie2011 5   159351203   ADRA1B  no  612 612 DonorAR2
54  Baillie2011 13  79259801    na  no  612 612 DonorAR2
54  Baillie2011 8   4452925 CSMD1   no  610 610 DonorAH

Arquivo B

study_id.x  sample_name chromosome  g_start
Baillie2011 DonorAH 8   4452925
Baillie2011 DonorBC 9   5491376
Baillie2011 DonorAH 8   5829283
Baillie2011 DonorCH 8   5829283

Resultado:

Arquivo A

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 4   57497067    na  no  612 612 DonorAR2
54  Baillie2011 X   154790187   TMLHE   no  612 612 DonorAR2
54  Baillie2011 5   159351203   ADRA1B  no  612 612 DonorAR2
54  Baillie2011 13  79259801    na  no  612 612 DonorAR2

Arquivo C

individual_id   study_id.x  chromosome  g_start gene    referencel1hs   SampleFile_num  id  sample_name
54  Baillie2011 8   4452925 CSMD1   no  610 610 DonorAH
    
por Roxane Dunbar 20.07.2017 / 14:12

1 resposta

1
perl -MFatal='open,close' -ali -ne '
   if ( @ARGV ) { # FileB readin
      if ( $. == 1 ) { push @names, @F;      }
      else           { push @A, join $/, @F; }
      print;
   } else { # FileA readin
      if ( $. == 1 ) {
         open FILEC, ">", "FileC.out";
         print FILEC $_;
         print;
         @remap =
            map {
               my $n = $names[$_];
               grep { $n eq $F[$_] } 0 .. $#F;
            } 0..$#names;
      } else {
         my $n = join $/, @F[@remap];
         if ( grep { $n eq $_ } @A ) { print FILEC $_; }
         else                        { print;          }
      }
   }
   eof and $. = 0;
   eof() and close FILEC;
' FileB FileA

Explicação

  • Fornecemos os 2 arquivos 'FileB' e 'FileA', nessa ordem, à linha de comando do Perl.
  • Durante o tempo em que o FileB está sendo lido, fazemos duas coisas dependendo se estamos na primeira ou em outra linha:
    • Para a primeira linha do FileB, armazenamos os nomes dos campos FileB no array @names .
    • Para outras linhas, preenchemos a matriz @A com os campos unidos pela nova linha \n fornecida por meio do $/ , que é o RS por padrão.
    • Em qualquer um desses casos, imprimimos as linhas em STDOUT, para que o Arquivo B seja lido de forma não destrutiva no modo Perl -i .
  • Agora, quando estivermos lendo o arquivo A, na primeira linha, abra um filehandle de gravação FILEC para podermos preencher o arquivo FileC.out .
    • Fazemos uma impressão para STDOUT, pois queremos que essa linha no FileB seja mantida.
    • Também imprimimos no filehandle FILEC, pois queremos que o cabeçalho também vá para o FileC.out.
    • Agora, essa é a etapa crucial em que um mapeamento dos campos do FileB é mapeado nos campos do FileA.
  • Para as não primeiras linhas no FileA, realizamos uma verificação de igualdade nesses campos remapeados com os dados já armazenados do FileB no array @A .
  • Caso seja encontrada uma correspondência, escreva essa linha em FileC.out, mas NÃO grave no FileA. Caso nenhuma correspondência seja encontrada, então nós escreveremos no FileA, mas NÃO no FileC.out.
  • Após o eof de um dos arquivos, redefinimos o contador de linha $. para 0, para que a igualdade de primeira linha verifique se ambos os arquivos podem ser executados.
  • Após o eof final (detectado via eof ()), fechamos o filehandle FILEC.
  • O módulo Fatal.pm é carregado com as funções open e close para fazer uma saída automática nessas operações.
por 20.07.2017 / 16:48

Tags