Imprimir linhas exclusivas


15

Existe alguma solução melhor para imprimir linhas exclusivas que não sejam uma combinação de sorte uniq?


1
O que você quer dizer com "melhor"?
Gabe.

@ gabe Não é necessário que o arquivo inteiro seja armazenado na memória, por exemplo.
23811 Let'Me_Be

Algumas versões sort(por exemplo: GNU coreutils) usam arquivos temporários e fusesort externo se a entrada for grande demais para caber na RAM. E a maioria das outras versões tem uma -mopção, para que isso possa ser feito explicitamente dividindo a entrada (por exemplo, com split), classificando cada bloco e depois mesclando os blocos
jhnc 23/01

Respostas:


25

Para imprimir cada linha idêntica apenas uma, em qualquer ordem:

sort -u

Para imprimir apenas as linhas exclusivas, em qualquer ordem:

sort | uniq -u

Para imprimir cada linha idêntica apenas uma vez, na ordem da primeira ocorrência: (para cada linha, imprima a linha se ainda não tiver sido vista e, em qualquer caso, aumente o contador visto)

awk '!seen[$0] {print}
     {++seen[$0]}'

Para imprimir apenas as linhas exclusivas, na ordem da primeira ocorrência: (registre cada linha seene também linesse for a primeira ocorrência; no final da entrada, imprima as linhas na ordem de ocorrência, mas apenas as que são vistas apenas uma vez)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
que tal awk '!seen[$0]++ {print}'?
asoundmove

10
Ou ainda mais curto awk '!seen[$0]++', pois o {print}é implícito por um comando vazio.
quazgar

3

Algumas (a maioria?) Versões de sortpossuem uma -ubandeira que faz a uniqparte diretamente. Pode haver algumas restrições de comprimento de linha, dependendo da implementação, mas você já as possui com o plain sort|uniq.


1
Er? sort -uvolta ao V7 pelo menos.
Geekosaur #

Hum ... pensei que me lembrava de Solaris ou AIX não ter isso. Estou errado, porém, ambos têm.
Mat

O Solaris e o AIX têm, -umas também têm, uma restrição de comprimento de linha de 512 caracteres. (Na verdade, eu acho que algo em torno de Solaris 9 Sun elevou-o para 5120. GNU ainda ganha, no entanto.)
geekosaur

@geekosaur: você tem certeza? O trabalho realizado para remover o limite de 512 bytes no comprimento da linha em classificação foi documentado em 'Teoria e Prática na Construção de uma Rotina de Classificação de Trabalho' por JP Linderman, Técnico da Bell System. Journal, 63, 1827-1843 (1984).
precisa

0

Perl funciona para você? Ele pode manter as linhas na ordem original, mesmo que as duplicatas não sejam adjacentes. Você também pode codificá-lo em Python, ou awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

Que pode ser reduzido para apenas

perl -ne 'print unless $lines{$_}++;'

Arquivo de entrada fornecido:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Rende a saída:

abc
def
ghi
jkl

Onde $ linhas estão sendo definidas?
Gregg Leventhal

Não é. Como não existe um use strict;ou use warnings;(na verdade, stricté o mais relevante aqui), não há reclamação sobre o uso %linesantes de ser definido. Se executado com restrições, seria necessário haver uma linha my %lines;antes do loop. Observe também que o hash é %lines; um elemento do hash é referenciado usando a $lines{$_}notação
27616 Jonathan Leffler

Eu acho que as sortsoluções podem ser melhores para grande quantidade de dados (o OP estava preocupado em "armazenar o arquivo inteiro na memória"). sortexecutará uma classificação fora do núcleo se os dados forem maiores que a memória disponível.
Kusalananda

0

Para a última parte da resposta mencionada em: Imprimir linhas exclusivas do @Gilles como resposta a esta pergunta, tentei eliminar a necessidade de usar dois hashes.

Esta solução é para: Imprimir apenas as linhas exclusivas, na ordem da primeira ocorrência:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

Aqui, "counter" armazena uma contagem de cada linha semelhante à processada anteriormente.
No final, imprimimos apenas as linhas que têm valor de contador como 1.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.