Saltar al contenido

Eliminar líneas duplicadas manteniendo el orden de las líneas

Bienvenido a nuestro espacio, aquí vas a encontrar la resolución de lo que buscas.

Solución:

Dudo que marque la diferencia, pero, por si acaso, he aquí cómo hacer lo mismo en Perl:

perl -ne 'print if ++$k$_==1' out.txt

Si el problema es mantener las líneas únicas en la memoria, tendrá el mismo problema que el awk intentaste. Entonces, otro enfoque podría ser:

cat -n out.txt | sort -k2 -k1n  | uniq -f1 | sort -nk1,1 | cut -f2-

Cómo funciona:

  1. En un sistema GNU, cat -n antepondrá el número de línea a cada línea después de una cierta cantidad de espacios y seguido de un personaje. cat canaliza esta representación de entrada a sort.

  2. sort‘s -k2 la opción le indica que solo considere los caracteres desde el segundo campo hasta el final de la línea al ordenar, y sort divide campos por defecto en espacios en blanco (o catespacios insertados y ).
    Cuando es seguido por -k1n, sort considera el segundo campo primero, y luego en segundo lugar, en el caso de idénticos -k2 campos: considera el primer campo pero ordenado numéricamente. Por lo tanto, las líneas repetidas se ordenarán juntas pero en el orden en que aparecieron.

  3. Los resultados se canalizan a uniq—a la que se le dice que ignore el primer campo (-f1 – y también separados por espacios en blanco)—y que da como resultado una lista de líneas únicas en el archivo original y se canaliza de vuelta a sort.
  4. Esta vez sort ordena en el primer campo (catnúmero de línea insertado) numéricamente, haciendo que el orden de clasificación vuelva a ser el que era en el archivo original y canaliza estos resultados a cut.
  5. Finalmente, cut elimina los números de línea que fueron insertados por cat. Esto se efectúa por cut imprimiendo solo desde el segundo campo hasta el final de la línea (y cutEl delimitador predeterminado de es un personaje).

Para ilustrar:

$ cat file
bb
aa
bb
dd
cc
dd
aa
bb
cc
$ cat -n file | sort -k2 | uniq -f1 | sort -k1 | cut -f2-
bb
aa    
dd
cc

#!/usr/bin/perl 
use DB_File;
tie %h, 'DB_File';

while(<>) not $h$_ and print and $h$_=1 

EDITAR 1: ¿Realmente funciona? (comparando)

Sol1 : Terdon et all Schwartzian-transform-like one-liner
    cat -n _1 | sort -uk2 | sort -nk1 | cut -f2-

Sol2 : perl  + DB_File (this answer)
    perl dbfile-uniq _1

Sol3 : PO (John W. Gill solution has a similar behavior)
    awk '!seen[$0]++' _1

Sol4: Terdon perl
    perl -ne 'print if ++$k$_==1' _1

Caso 1: 100_000_000 números aleatorios (5 dígitos cada uno), 566 Mbytes, 31_212 valores diferentes:

$ while true ; do echo $RANDOM; done | head -100000000 > _1

Caso 2: 50_000_000 números aleatorios (10 dígitos cada uno), 516 Mbytes, 48_351_464 valores diferentes:

$ shuf _1 |  sed 'N;s/n/ /' > _11

(los siguientes números no son muy precisos):

┌────────┬────────┬────────────────┬────────┬──────┐
│        │ Sol1   │ Sol2           │ Sol3   │ Sol4 │
│        │ sort...│ perl DB        │ awk    │ perl │
├────────┼────────┼────────────────┼────────┼──────┤
│ case 1 │ 6m15   │ 6m17           │ 0m28   │ 0m28 │
├────────┼────────┼────────────────┼────────┴──────┤
│ case 2 │ 11m15  │ 81m44          │ out of memory │
├────────┼────────┼────────────────┼────────┬──────┤
│ case 2 │        │ 5m54 /cache=2G │        │      │
└────────┴────────┴────────────────┴────────┴──────┘

sol2 con caché es:

use DB_File;
use Fcntl ;

$DB_HASH->'cachesize' = 2000_000_000;
tie %h, 'DB_File', "_my.db", O_RDWR|O_CREAT|O_TRUNC, 0640, $DB_HASH;

while(<>) not $h$_ and print and $h$_=1 

Ordenar también se puede optimizar agregando una opción de tamaño de caché (no hecho).

Una conclusión rápida:

  • sort es un comando fantástico!

Agradecemos que desees reafirmar nuestro análisis exponiendo un comentario y puntuándolo te estamos agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *