Imprimir líneas únicas

15

¿Existe alguna solución mejor para imprimir líneas únicas que no sea una combinación de sorty uniq?

Déjame ser
fuente
1
¿Qué quieres decir con "mejor"?
Gabe.
@gabe No requiere que todo el archivo se almacene en la memoria, por ejemplo.
Let_Me_Be
Algunas versiones de sort(por ejemplo, GNU coreutils) usan archivos temporales y mergesort externo si la entrada es demasiado grande para caber en la RAM. Y la mayoría de las otras versiones tienen una -mopción para que esto se pueda hacer explícitamente fragmentando la entrada (por ejemplo, con split), clasificando cada fragmento y luego fusionando los fragmentos
jhnc

Respuestas:

25

Para imprimir cada línea idéntica solo una, en cualquier orden:

sort -u

Para imprimir solo las líneas únicas, en cualquier orden:

sort | uniq -u

Para imprimir cada línea idéntica solo una vez, en el orden de su primera aparición: (para cada línea, imprima la línea si aún no se ha visto, luego, en cualquier caso, incremente el contador visto)

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

Para imprimir solo las líneas únicas, en el orden de su primera aparición: (registre cada línea en seen, y también linessi es la primera aparición; al final de la entrada, imprima las líneas en orden de aparición pero solo las que se ven solo una vez)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'
Gilles 'SO- deja de ser malvado'
fuente
8
¿qué tal awk '!seen[$0]++ {print}'?
asoundmove
10
O incluso más corto awk '!seen[$0]++', ya que {print}está implícito en un comando vacío.
quazgar
3

Algunas versiones (¿la mayoría?) sortTienen una -ubandera que hace la uniqparte directamente. Sin embargo, podría haber algunas restricciones de longitud de línea dependiendo de la implementación, pero ya las tenía con plain sort|uniq.

Estera
fuente
1
Er? sort -uvuelve al menos a V7.
geekosaur
Hum ... pensé que recordaba que Solaris o AIX no tenían eso. Sin embargo, estoy equivocado, ambos lo tienen.
Mat
Solaris y AIX tienen -upero también tienen una restricción de longitud de línea de 512 caracteres. (En realidad, creo que en algún lugar alrededor de Solaris 9 Sun aumentó a 5120. GNU todavía gana, sin embargo.)
geekosaur
@geekosaur: ¿estás seguro? El trabajo realizado para eliminar el límite de 512 bytes en la longitud de la línea en especie fue documentado en 'Teoría y práctica en la construcción de una rutina de clasificación de trabajo' por JP Linderman, técnico del sistema Bell. Journal, 63, 1827-1843 (1984).
Jonathan Leffler el
0

¿Perl trabaja para ti? Puede mantener las líneas en el orden original, incluso si los duplicados no son adyacentes. También puede codificarlo en Python, o awk.

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

Que se puede acortar a solo

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

Archivo de entrada dado:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Produce la salida:

abc
def
ghi
jkl
Jonathan Leffler
fuente
¿Dónde se define $ lines?
Gregg Leventhal
No lo es Como no hay un use strict;o use warnings;(en realidad, es strictlo más relevante aquí), no hay ninguna queja sobre el uso %linesantes de que se defina. Si se ejecuta con restricciones, debe haber una línea my %lines;antes del bucle. Tenga en cuenta también que el hash es %lines; Se hace referencia a un elemento del hash utilizando la $lines{$_}notación.
Jonathan Leffler
Creo que las sortsoluciones pueden ser mejores para una gran cantidad de datos (el OP estaba preocupado por "almacenar todo el archivo en la memoria"). sortrealizará una ordenación fuera del núcleo si los datos son más grandes que la memoria disponible.
Kusalananda
0

Para la última parte de la respuesta mencionada en: Imprimir líneas únicas de @Gilles como respuesta a esta pregunta, traté de eliminar la necesidad de usar dos hashes.

Esta solución es para: Imprimir solo las líneas únicas, en el orden de su primera aparición:

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

Aquí, "contador" almacena un recuento de cada línea que es similar a la procesada anteriormente.
Al final, imprimimos solo aquellas líneas, que tienen un valor de contador como 1.

Sarfraaz Ahmed
fuente