Comparando arquivos com base em 5 campos usando Awk and Bash

3

Eu quero comparar Arquivo1 e Arquivo2 (Separado por espaços) usando cinco campos (Coluna 1,2,4,5,6).

* Lógica: * Se as colunas 1 e 2 do Arquivo1 e Arquivo2 corresponderem exatamente e se o Arquivo2 tiver os mesmos caracteres que qualquer um dos caracteres presentes nas colunas 4 e 5 do arquivo1, essas linhas de file1 e file2 são concatenados e redirecionados como saída.

Arquivo1:

s2/80   20      .       A       T       86      N=2     F=5;U=4
s2/20   10      .       G       T       90      N=2     F=5;U=4
s2/90   60      .       C       G       30      N=2     F=5;U=4

Arquivo2:

s2/90   60      .       G       G       97      N=2     F=5;U=4
s2/80   20      .       A       A       20      N=2     F=5;U=4
s2/15   11      .       A       A       22      N=2     F=5;U=4
s2/90   21      .       C       C       82      N=2     F=5;U=4
s2/20   10      .       G       G       99      N=2     F=5;U=4
s2/80   10      .       T       G       11      N=2     F=5;U=4
s2/90   60      .       G       T       55      N=2     F=5;U=4

Saída:

s2/80  20 . A   T   86  N=2 F=5;U=4  s2/80  20  . A   A   20   N=2     F=5;U=4
s2/20  10 . G   T   90  N=2 F=5;U=4  s2/20  10  . G   G   99   N=2     F=5;U=4
s2/90  60 . C   G   30  N=2 F=5;U=4  s2/90  60  . G   G   97   N=2     F=5;U=4

Sou novo neste campo e gostaria de receber qualquer orientação.

    
por Namrata 13.08.2013 / 17:06

1 resposta

5

Aqui está uma solução usando apenas awk . Coloque o código abaixo em um arquivo chamado ex.awk :

BEGIN{}
FNR==NR{
    k=$1" "$2
    a[k]=$4" "$5
    b[k]=$0
    c[k]=$4
    d[k]=$5
    next
}

{ k=$1" "$2
  lc=c[k]
  ld=d[k]
  # file1 file2
  if ((k in a) && ($4==$5) && (lc==$4) || (ld==$5)) print b[k]" "$0
}

E, em seguida, execute-o assim com os dois arquivos acima:

$ awk -f ex.awk file1 file2

Exemplo

O sed é apenas para formatar a saída para o StackExchange!

$ awk -f ex.awk file1 file2 | sed 's/[ ]\+/  /g'
s2/90  60  .  C  G  30  N=2  F=5;U=4  s2/90  60  .  G  G  97  N=2  F=5;U=4
s2/80  20  .  A  T  86  N=2  F=5;U=4  s2/80  20  .  A  A  20  N=2  F=5;U=4
s2/20  10  .  G  T  90  N=2  F=5;U=4  s2/20  10  .  G  G  99  N=2  F=5;U=4

Uma mudança nos requisitos

O OP mencionou nos comentários abaixo que ele gostaria da solução definitiva para descartar quaisquer linhas onde as colunas 4 e 5 de file1 correspondessem às colunas 4 e 5 de file2 .

Por exemplo, adicione esta linha a ambos file1 & file2 :

s2/40   40      .       S       S       90      N=2     F=5;U=4

Uma adição de linha única à solução original pode abordar essa alteração específica nos requisitos.

if ((k in a) && (lc==$4) && (ld==$5)) next

Novo exemplo

ex2.awk :

BEGIN{}
FNR==NR{
  k=$1" "$2
  a[k]=$4" "$5
  b[k]=$0
  c[k]=$4
  d[k]=$5
  next
}

{ k=$1" "$2
  lc=c[k]
  ld=d[k]
  if ((k in a) && (lc==$4) && (ld==$5)) next
  if ((k in a) && ($4==$5) && (lc==$4) || (ld==$5)) print b[k]" "$0
}

Execução do novo script awk , ex2.awk :

$ awk -f ex2.awk file1 file2 | sed 's/[ ]\+/  /g'
s2/90  60  .  C  G  30  N=2  F=5;U=4  s2/90  60  .  G  G  97  N=2  F=5;U=4
s2/80  20  .  A  T  86  N=2  F=5;U=4  s2/80  20  .  A  A  20  N=2  F=5;U=4
s2/20  10  .  G  T  90  N=2  F=5;U=4  s2/20  10  .  G  G  99  N=2  F=5;U=4
    
por 13.08.2013 / 21:54

Tags