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 -ibandera ("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
Para hacer una copia de seguridad del archivo original, puede agregar una extensión al indicador -i [ perldoc.perl.org/perlrun.html]
Steve Schnepp
Normalmente soy un fan de Perl, pero me encontré con este ejemplo de rubí, que tiene la ventaja de ser más corto: 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)
mivk
según el comentario a continuación, shufcarga 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?
Bueno, estoy usando gnu-coreutils 7.1 (instalación estándar de gentoo), que tiene ordenamiento con esta opción, no estoy seguro de cuándo apareció o si está en otras implementaciones.
Jim T
1
La función se comprometió el 10 de diciembre de 2005, el lanzamiento siguiente fue 5.94, así que supongo que ha estado disponible desde esa versión.
Jim T
41
En OS X puede instalar gnu coreutils con homebrew: brew install coreutilstodas las utilidades tienen el prefijo ag así: gsort --random-sorto gshuffuncionarán como se esperaba
mike
3
+1 @mike. Yo uso Macports y también tenía gsorte gshufinstalé cuando lo hiceport install coreutils
Noah Sussman
10
Esta solución solo es buena si sus líneas no tienen repeticiones. Si es así, todas las instancias de esa línea aparecerán una al lado de la otra. Considere usar en su shuflugar (en Linux).
Ali J
118
shuf Es la mejor manera.
sort -Res dolorosamente lento. Intenté ordenar el archivo de 5GB. Me di por vencido después de 2,5 horas. Luego lo shufordené en un minuto.
@benroth: Por lo que puedo decir, con recuentos de entrada realmente grandes, aumentar la memoria puede ayudar un poco , pero sigue siendo lento en general. En mis pruebas, la clasificación de un archivo de entrada de 1 millón de línea creada con la seq -f 'line %.0f' 1000000tomó el mismo, a largo tiempo de proceso (mucho, mucho más tiempo que con shuf), sin importar la cantidad de memoria Asigné.
mklement0
1
@ mklement0, ¡tienes razón! Lo intenté con un archivo mucho más grande que el que tenía antes, y el hash parece ser el cuello de botella.
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.
Esto funciona y es una solución creativa, pero eliminará los espacios en blanco iniciales en las líneas.
Chris Lutz
@Chris cambiando el último corte a | sed 's / ^ [^ \ t] * \ t //' debería arreglar eso
bdonlan
Felicitaciones a la simplicidad del enfoque.
Shashikant Kore
3
+1 para la conformidad con POSIX (excepto $RANDOM), pero -1 para eliminar los datos. Reemplazar while read fcon while IFS= read -r fevitará readque 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 cuteliminen 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-
Richard Hansen
3
@Richard Hansen: Gracias, estos cambios sugeridos son obviamente apropiados, he editado mi publicación.
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,ces la abreviatura de -e 'use module qw(a b c);'.)
La razón por la que darle un simple -ino funciona para barajar en el lugar es porque Perl espera que printsuceda 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.
mezclará los archivos en su lugar. ( -nsignifica "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/^/mes necesario porque $_=<>se ha hecho implícitamente con un archivo completo en lugar de líneas).
Reiterando ese tipo -R no existe en OS X, pero +1 para algunas excelentes respuestas de Perl, y una excelente respuesta en general.
Chris Lutz
Podrías instalar GNU coreutils en OS X, pero (como he hecho en el pasado) debes tener cuidado de no romper las herramientas integradas ... Dicho esto, OP está en Redhat Linux, que definitivamente tiene GNU estándar de coreutils.
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.
Respuestas:
¡Y obtienes un one-liner de Perl!
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:
No probado, pero con suerte funciona.
fuente
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 exceptoKilled
. ¿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
fuente
brew install coreutils
todas las utilidades tienen el prefijo ag así:gsort --random-sort
ogshuf
funcionarán como se esperabagsort
egshuf
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 loshuf
ordené en un minuto.fuente
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 conshuf
), sin importar la cantidad de memoria Asigné.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.
fuente
$RANDOM
), pero -1 para eliminar los datos. Reemplazarwhile read f
conwhile 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 secut
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:
Y para imprimir una sola línea aleatoria:
Pero vea esta publicación para conocer los inconvenientes de python
random.shuffle()
. No funcionará bien con muchos elementos (más de 2080).fuente
Relacionado con la respuesta de Jim:
Mi
~/.bashrc
contiene lo siguiente: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:
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 queprint
suceda en el mismo bucle en el que se está leyendo el archivo, yprint shuffle <>
no genera salida hasta que todos los archivos de entrada se han leído y cerrado.Como solución temporal más breve,
mezclará los archivos en su lugar. (
-n
significa "envolver el código en unwhile (<>) {...}
bucle;BEGIN{undef$/}
hace que Perl opere en archivos a la vez en lugar de líneas a la vez, ysplit/^/m
es necesario porque$_=<>
se ha hecho implícitamente con un archivo completo en lugar de líneas).fuente
Cuando instalo coreutils con homebrew
shuf
está disponible comon
.fuente
g
lo que seshuf
convirtiógshuf
para mí.Mac OS X con DarwinPorts:
fuente
FreeBSD tiene su propia utilidad aleatoria:
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.
fuente
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
fuente
O consígalo en MacPorts:
y / o
fuente