¿Cómo puedo aleatorizar las líneas en un archivo usando herramientas estándar en Red Hat Linux?
No tengo el shuf
comando, así que estoy buscando algo como una perl
o awk
una línea que logre la misma tarea.
¿Cómo puedo aleatorizar las líneas en un archivo usando herramientas estándar en Red Hat Linux?
No tengo el shuf
comando, así que estoy buscando algo como una perl
o awk
una línea que logre la misma tarea.
Respuestas:
¡Y obtienes un one-liner de Perl!
perl -MList::Util -e 'print List::Util::shuffle <>'
Utiliza un módulo, pero el módulo es parte de la distribución del código Perl. Si eso no es lo suficientemente bueno, puede considerar lanzar el suyo.
Intenté usar esto con la -i
bandera ("editar en el lugar") para que editara el archivo. La documentación sugiere que debería funcionar, pero no es así. Todavía muestra el archivo mezclado en stdout, pero esta vez elimina el original. Le sugiero que no lo use.
Considere un script de shell:
#!/bin/sh
if [[ $# -eq 0 ]]
then
echo "Usage: $0 [file ...]"
exit 1
fi
for i in "$@"
do
perl -MList::Util -e 'print List::Util::shuffle <>' $i > $i.new
if [[ `wc -c $i` -eq `wc -c $i.new` ]]
then
mv $i.new $i
else
echo "Error for file $i!"
fi
done
No probado, pero con suerte funciona.
ruby -e 'puts STDIN.readlines.shuffle'
. Sería necesario realizar pruebas en grandes entradas para ver si la velocidad es comparable. (también funciona en OS X)
shuf
carga todo en la memoria, por lo que no funciona con un archivo realmente enorme (el mío es ~ 300GB tsv). Este script de Perl también falló en el mío, pero sin ningún error excepto Killed
. ¿Alguna idea de si la solución de Perl también está cargando todo en la memoria, o hay algún otro problema que estoy encontrando?
Um, no olvidemos
sort --random-sort
brew install coreutils
todas las utilidades tienen el prefijo ag así: gsort --random-sort
o gshuf
funcionarán como se esperaba
gsort
e gshuf
instalé cuando lo hiceport install coreutils
shuf
lugar (en Linux).
shuf
Es la mejor manera.
sort -R
es dolorosamente lento. Intenté ordenar el archivo de 5GB. Me di por vencido después de 2,5 horas. Luego lo shuf
ordené en un minuto.
sort -R
es lenta es que calcula un hash para cada línea. De los documentos: " Ordene por hash de las claves de entrada y luego clasifique los valores hash " .
shuf
carga todo en la memoria.
seq -f 'line %.0f' 1000000
tomó el mismo, a largo tiempo de proceso (mucho, mucho más tiempo que con shuf
), sin importar la cantidad de memoria Asigné.
cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Lea el archivo, anteponga cada línea con un número aleatorio, ordene el archivo por esos prefijos aleatorios, luego corte los prefijos. Una línea que debería funcionar en cualquier caparazón semi-moderno.
EDITAR: incorporó los comentarios de Richard Hansen.
$RANDOM
), pero -1 para eliminar los datos. Reemplazar while read f
con while IFS= read -r f
evitará read
que se eliminen los espacios en blanco iniciales y finales (consulte esta respuesta ) y evitará el procesamiento de barras invertidas. El uso de una cadena aleatoria de longitud fija evitará que se cut
eliminen los espacios en blanco iniciales. Resultado: cat yourfile.txt | while IFS= read -r f; do printf "%05d %s\n" "$RANDOM" "$f"; done | sort -n | cut -c7-
Una sola línea para Python:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile
Y para imprimir una sola línea aleatoria:
python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile
Pero vea esta publicación para conocer los inconvenientes de python random.shuffle()
. No funcionará bien con muchos elementos (más de 2080).
Relacionado con la respuesta de Jim:
Mi ~/.bashrc
contiene lo siguiente:
unsort ()
{
LC_ALL=C sort -R "$@"
}
Con sort, -R
= de GNU coreutils --random-sort
, que genera un hash aleatorio de cada línea y las ordena. El hash aleatorio en realidad no se usaría en algunas configuraciones regionales en algunas versiones más antiguas (con errores), lo que hace que devuelva una salida ordenada normal, por lo que configuré LC_ALL=C
.
Relacionado con la respuesta de Chris:
perl -MList::Util=shuffle -e'print shuffle<>'
es un delineador ligeramente más corto. ( -Mmodule=a,b,c
es la abreviatura de -e 'use module qw(a b c);'
.)
La razón por la que darle un simple -i
no funciona para barajar en el lugar es porque Perl espera que print
suceda en el mismo bucle en el que se está leyendo el archivo, y print shuffle <>
no genera salida hasta que todos los archivos de entrada se han leído y cerrado.
Como solución temporal más breve,
perl -MList::Util=shuffle -i -ne'BEGIN{undef$/}print shuffle split/^/m'
mezclará los archivos en su lugar. ( -n
significa "envolver el código en un while (<>) {...}
bucle; BEGIN{undef$/}
hace que Perl opere en archivos a la vez en lugar de líneas a la vez, y split/^/m
es necesario porque $_=<>
se ha hecho implícitamente con un archivo completo en lugar de líneas).
FreeBSD tiene su propia utilidad aleatoria:
cat $file | random | ...
Está en / usr / games / random, así que si no ha instalado juegos, no tiene suerte.
Podría considerar instalar puertos como textproc / rand o textproc / msort. Estos pueden estar disponibles en Linux y / o Mac OS X, si la portabilidad es una preocupación.
En OSX, obteniendo lo último de http://ftp.gnu.org/gnu/coreutils/ y algo como
./configure make sudo make install
... debería darle / usr / local / bin / sort --random-sort
sin estropear / usr / bin / sort
O consígalo en MacPorts:
$ sudo port install coreutils
y / o
$ /opt/local//libexec/gnubin/sort --random-sort