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

6

Eu tenho um arquivo de entrada ( input.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

Note que a primeira linha não faz parte do arquivo real, eu adicionei aqui para maior clareza .

Estou tentando extrair os valores de id1 e id2 para dois arquivos separados chamados unique.txt e duplicate.txt .

Se o valor da coluna weight for maior que 1,5, significa que tenho IDs duplicados . Nesse caso, moverei o valor id1 para unique.txt file e id2 value para duplicate.txt file.

Se minha coluna de peso for menor que 1,5, significa que não tenho valores duplicados. Portanto, nesse caso, moverei os arquivos id1 e id2 para unique.txt .

Então, para a entrada acima, estou esperando a saída como

Para o arquivo unique.txt ,

53723848 timburnes
764157 ericcartman
56797854 ericcartman

Para o arquivo duplicate.txt ,

12651711 timburnes
53530214 timburnes
52986038 ericcartman

Eu posso descobrir as duplicatas usando o código abaixo.

Para obter os valores maiores que 1,5 com base na quarta 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 como 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 recebendo a saída como

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

No entanto, a saída que estou esperando é,

cat unique.txt
17412193 ericcartman
21757330 andrewruss
54678379 andrewruss
cat duplicate.txt
43979400 ericcartman
    
por Ramesh 06.05.2014 / 18:05

3 respostas

7

Aqui está a awk solution:

$ 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 o 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
    
por 06.05.2014 / 19:13
6
$ 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
    
por 06.05.2014 / 18:41
6

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

Eu não estou verificando duplicatas aqui, se eu entendi sua pergunta corretamente, você já fez isso e se algo é um dupe ou não depende do valor do último campo. Se eu estiver entendendo mal algo, 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
    
por 06.05.2014 / 18:59

Tags