Remove duplicados em cada linha de um arquivo

7

Como posso remover duplicatas em cada linha, por exemplo, aqui?

1 1 1 2 1 2 3
5 5 4 1 2 3 3

Gostaria de obter esta saída:

1 2 3 
5 4 1 2 3

Existem muitas linhas (100.000) e em cada linha eu quero valores únicos. Perl pode ser o mais rápido, mas como posso fazê-lo em Perl ou Bash?

    
por Arash 19.12.2012 / 18:05

3 respostas

12

Aqui está uma opção usando o awk:

awk '{ while(++i<=NF) printf (!a[$i]++) ? $i FS : ""; i=split("",a); print ""}' infile > outfile

Editar Atualizado com comentários:

  1. while (++i<=NF)

    Inicializa o loop while, precificando "i", pois $ 0 é a linha completa no awk.

    Então começa em $ 1 (primeiro campo). Faz um loop na linha até o final (menor ou igual a 'NF'), que é embutido no awk para "Número de campos"). O separador de campos padrão é um espaço, você pode alterar o separador padrão facilmente.

  2. printf (!a[$i]++) ? $i FS : ""

    Esta é uma operação ternária .

    Portanto, se a entrada não estiver na matriz !a[$i]++ , ela imprimirá $ i, se for, imprimirá "". (Você poderia remover o ! e inverter o $i FS : "" se você não gostar desse jeito).

  3. i=split("",a)

    Normalmente, isso é uma divisão nula. Nesse caso, ele redefine a linha I para a próxima.

  4. print ""

    termina a linha da saída (não 100% porque, na verdade), caso contrário você teria uma saída de:

    1 2 3 5 4 1 2 3 em vez de 1 2 3 e 5 4 1 2 3

por 19.12.2012 / 18:27
5

Como ruby vem com qualquer distribuição Linux que eu conheça:

ruby -e 'STDIN.readlines.each { |l| l.split(" ").uniq.each { |e| print "#{e} " }; print "\n" }' < test

Aqui, test é o arquivo que contém os elementos.

Para explicar o que este comando faz - embora o Ruby possa quase ser lido da esquerda para a direita:

  • Leia a entrada (que vem de < test através do seu shell)
  • Percorra cada linha da entrada
  • Divida a linha com base em um espaço separando os itens em uma matriz ( split(" ") )
  • Obtenha os elementos exclusivos dessa matriz (em ordem)
  • Para cada elemento único, imprima-o, incluindo um espaço ( print "#{e} " )
  • Imprima uma nova linha quando terminarmos com os elementos exclusivos
por 19.12.2012 / 18:21
2

Não piada pura, mas ...:

while read line; do
    printf "%s\n" $line | sort -u | tr '\n' ' '
    echo ''
done < file

As linhas serão classificadas como um subproduto.

    
por 19.12.2012 / 22:03