Existe uma solução perl ou awk para este problema?

Existe uma solução perl ou awk para este problema?

Eu tenho um arquivo de entrada (entrada.txt) como abaixo.

id1      id2       name    weight 
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781

Observe quea primeira linha não faz parte do arquivo real, adicionei-a aqui para maior clareza.

Estou tentando extrair os valores de id1e id2para 2 arquivos separados chamadosúnico.txteduplicado.txt.

Se weighto valor da minha coluna for maior que 1,5, significa que tenhoIDs duplicados. Nesse caso, moverei o id1valor para unique.txtarquivo e id2o valor para duplicate.txtarquivo.

Se minha coluna de peso for menor que 1,5, significa que não tenho valores duplicados. Então, neste caso, vou mover ambos id1e id2para único.txtarquivo.

Portanto, para a entrada acima, estou esperando a saída como,

Paraúnico.txtarquivo,

53723848 timburnes
764157 ericcartman
56797854 ericcartman

Paraduplicado.txtarquivo,

12651711 timburnes
53530214 timburnes
52986038 ericcartman

Posso descobrir as duplicatas usando o código abaixo.

Para obter valores maiores que 1,5 com base na 4ª coluna,

awk -F" " '$4 >= 1.5 { print $1" " $2" " $3" " $4}' file1.txt > Output.txt

Agora, para valores maiores que 1,5, posso usar o código abaixo para mesclar os IDs duplicados com base em seus nomes.

  perl -ane 'foreach(@F[0..1]){$k{$F[2]}{$_}++}
           END{
                foreach $v (sort keys(%k)){
                    print "$_ " foreach(keys(%{$k{$v}})); 
                    print "$v\n"
                }; 
            } ' Output.txt

No entanto, não consigo obter o resultado da maneira que gosto na abordagem acima.

EDITAR:

Estou executando o comando para minha entrada conforme abaixo.

awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
17412193 43979400 ericcartman 2.16667
21757330 54678379 andrewruss 0.55264
END 

Estou obtendo a saída como,

-bash-3.2$ cat unique.txt
21757330 a.andreev
-bash-3.2$ cat duplicate.txt
43979400 ericcartman

No entanto, o resultado que espero é,

cat unique.txt
17412193 ericcartman
21757330 andrewruss
54678379 andrewruss
cat duplicate.txt
43979400 ericcartman

Responder1

Aqui está awka solução:

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' file
--unique.txt--
764157 ericcartman
56797854 ericcartman
53723848 timburnes

--duplicate.txt--
53530214 timburnes
52986038 ericcartman
12651711 timburnes

Com seu segundo exemplo:

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' << END
> 17412193 43979400 ericcartman 2.16667
> 21757330 54678379 andrewruss 0.55264
END
--unique.txt--
21757330 andrewruss
54678379 andrewruss
17412193 ericcartman

--duplicate.txt--
43979400 ericcartman

Responder2

$ awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781
END

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

Responder3

Aqui está um Perl:

perl -lane '$F[3]>1.5 ? print STDERR "$F[1] $F[2]" : print STDOUT "$F[0] $F[2]"'\
 input.txt 2> duplicate.txt > unique.txt

Não estou verificando duplicatas aqui, se entendi bem sua pergunta, você já fez isso e se algo é bobo ou não depende do valor do último campo. Se eu estiver entendendo mal alguma coisa, por favor me avise e atualizarei isso.

O código acima produz

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

informação relacionada