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:
-
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 unpersonaje. cat
canaliza esta representación de entrada asort
. -
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, ysort
divide campos por defecto en espacios en blanco (ocat
espacios 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. - 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 asort
. - Esta vez
sort
ordena en el primer campo (cat
nú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 acut
. - Finalmente,
cut
elimina los números de línea que fueron insertados porcat
. Esto se efectúa porcut
imprimiendo solo desde el segundo campo hasta el final de la línea (ycut
El delimitador predeterminado de es unpersonaje).
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.