Sí, hay algunas otras buenas respuestas en esa pregunta original también.
Ruggiero Spearman
entonces, ¿estabas haciendo una lista de palabras de wpa? (solo una suposición aleatoria)
thahgr
Respuestas:
360
Puedes usar shuf. Al menos en algunos sistemas (no parece estar en POSIX).
Como señaló jleedev: sort -Rtambién podría ser una opción. En algunos sistemas al menos; Bueno, te haces una idea. Se ha señalado que sort -Rrealmente no se baraja, sino que clasifica los elementos según su valor hash.
[Nota del editor: sort -Rcasi se baraja, excepto que las líneas duplicadas / las claves de clasificación siempre terminan una al lado de la otra . En otras palabras: solo con líneas / teclas de entrada únicas es una verdadera combinación aleatoria. Si bien es cierto que el orden de salida está determinado por los valores hash , la aleatoriedad proviene de elegir una función hash aleatoria ; consulte el manual .]
shufy sort -Rdifieren ligeramente, porque sort -Rordena aleatoriamente los elementos según el hash de ellos, es decir, sort -Rjuntará los elementos repetidos, mientras shufbaraja todos los elementos aleatoriamente.
SeMeKh
146
Para usuarios de OS X:, brew install coreutilsluego use gshuf ...(:
ELLIOTTCABLE
15
sort -Ry shufdebería ser visto como completamente diferente. sort -REs determinista. Si lo llama dos veces en diferentes momentos en la misma entrada, obtendrá la misma respuesta. shuf, por otro lado, produce una salida aleatoria, por lo que probablemente dará una salida diferente en la misma entrada.
EfForEffort
18
Eso no es correcto. "sort -R" usa una clave aleatoria diferente cada vez que la invoca, por lo que produce una salida diferente cada vez.
Mark Pettit
3
Nota sobre la aleatoriedad: según los documentos de GNU, "Por defecto, estos comandos usan un generador pseudoaleatorio interno inicializado por una pequeña cantidad de entropía, pero pueden dirigirse a usar una fuente externa con la opción --random-source = file".
Royce Williams
85
Perl one-liner sería una versión simple de la solución de Maxim
Este fue el único script en esta página que devolvió líneas REALES aleatorias. Otras soluciones awk a menudo imprimen resultados duplicados.
Felipe Alvarez
1
Pero tenga cuidado porque en el exterior perderá una línea :) Simplemente se unirá con otra línea :)
JavaRunner
@JavaRunner: supongo que estás hablando de entradas sin un seguimiento \n; sí, eso \ndebe estar presente, y generalmente lo está , de lo contrario obtendrá lo que describe.
mklement0
1
Maravillosamente conciso. Sugiero reemplazar <STDIN>con <>, por lo que la solución también funciona con la entrada de archivos .
mklement0
60
Esta respuesta complementa las muchas excelentes respuestas existentes de las siguientes maneras:
Las respuestas existentes se agrupan en funciones de shell flexibles :
Las funciones toman no solo stdinentrada, sino también argumentos de nombre de archivo
Las funciones toman pasos adicionales para manejar SIGPIPEde la manera habitual (terminación silenciosa con código de salida 141), en lugar de romperse ruidosamente. Esto es importante cuando se canaliza la salida de la función a una tubería que se cierra temprano, como cuando se canaliza a head.
Se realiza una comparación de rendimiento .
Función compatible con POSIX basada en awk, sortycut , adaptada de la propia respuesta del OP :
shuf(){ python -c '
import sys, random, fileinput; from signal import signal, SIGPIPE, SIG_DFL;
signal(SIGPIPE, SIG_DFL); lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write("".join(lines))
'"$@";}
Consulte la sección inferior para obtener una versión de Windows de esta función.
Nota: Estos números se obtuvieron en un iMac de finales de 2012 con Intel Core i5 de 3.2 GHz y una unidad Fusion, con OSX 10.10.3. Si bien los tiempos variarán con el sistema operativo utilizado, las especificaciones de la máquina, la awkimplementación utilizada (por ejemplo, la awkversión BSD utilizada en OSX suele ser más lenta que GNU awky especialmente mawk), esto debería proporcionar una sensación general de rendimiento relativo .
El archivo de entrada es un archivo de 1 millón de líneas producido con seq -f 'line %.0f' 1000000.
Los tiempos se enumeran en orden ascendente (el más rápido primero):
shuf
0.090s
Ruby 2.0.0
0.289s
Perl 5.18.2
0.589s
Pitón
1.342scon Python 2.7.6; 2.407s(!) con Python 3.4.2
awk+ sort+cut
3.003scon BSD awk; 2.388scon GNU awk(4.1.1); 1.811scon mawk(1.3.4);
Para una mayor comparación, las soluciones no se empaquetan como las funciones anteriores:
sort -R (no es una combinación aleatoria verdadera si hay líneas de entrada duplicadas)
10.661s - asignar más memoria no parece hacer la diferencia
Scala
24.229s
bash bucles + sort
32.593s
Conclusiones :
Úselo shuf, si puede , es el más rápido con diferencia.
A Ruby le va bien, seguido de Perl .
Python es notablemente más lento que Ruby y Perl, y, comparando las versiones de Python, 2.7.6 es bastante más rápido que 3.4.1
Use el combo + awk+ compatible con POSIX como último recursosortcut ; el que awkla aplicación utiliza asuntos ( mawkes más rápido que GNU awk, BSD awkes más lento).
Mantenerse alejado de sort -R, bashbucles, y Scala.
Versiones de Windows de la solución Python (el código de Python es idéntico, excepto por las variaciones en las citas y la eliminación de las declaraciones relacionadas con la señal, que no son compatibles con Windows):
Para PowerShell (en Windows PowerShell, tendrá que ajustar $OutputEncodingsi desea enviar caracteres no ASCII a través de la canalización):
# Call as `shuf someFile.txt` or `Get-Content someFile.txt | shuf`function shuf {
$Input | python -c @'
import sys, random, fileinput;
lines=[line for line in fileinput.input()];
random.shuffle(lines); sys.stdout.write(''.join(lines))
'@ $args
}
Tenga en cuenta que PowerShell puede barajar de forma nativa a través de su Get-Randomcmdlet (aunque el rendimiento puede ser un problema); p.ej: Get-Content someFile.txt | Get-Random -Count ([int]::MaxValue)
Para cmd.exe(un archivo por lotes):
Guardar en archivo shuf.cmd, por ejemplo:
@echo off
python -c "import sys, random, fileinput; lines=[line for line in fileinput.input()]; random.shuffle(lines); sys.stdout.write(''.join(lines))"%*
SIGPIPE no existe en Windows, así que utilicé esta línea simple:python -c "import sys, random; lines = [x for x in sys.stdin.read().splitlines()] ; random.shuffle(lines); print(\"\n\".join([line for line in lines]));"
eleg
@elig: Gracias, pero omitir from signal import signal, SIGPIPE, SIG_DFL; signal(SIGPIPE, SIG_DFL);de la solución original es suficiente y conserva la flexibilidad de poder también pasar argumentos de nombre de archivo ; no es necesario cambiar nada más (excepto las citas). Consulte la nueva sección que he agregado en fondo.
mklement0
27
Utilizo un pequeño script en perl, al que llamo "sin ordenar":
#!/usr/bin/perl
use List::Util'shuffle';@list=<STDIN>;
print shuffle(@list);
También tengo una versión delimitada por NULL, llamada "unsort0" ... útil para usar con find -print0 y así sucesivamente.
PD: Votado como 'shuf' también, no tenía idea de que estaba allí en coreutils en estos días ... lo anterior aún puede ser útil si sus sistemas no tienen 'shuf'.
Bien hecho; Sugiero reemplazar <STDIN>con <>para que la solución funcione con la entrada de archivos también.
mklement0
20
Aquí hay un primer intento que es fácil para el codificador pero difícil para la CPU, que antepone un número aleatorio a cada línea, los ordena y luego elimina el número aleatorio de cada línea. En efecto, las líneas se ordenan al azar:
Bien, depuro con head myfile | awk .... Entonces solo lo cambio a gato; por eso lo dejaron allí.
Ruggiero Spearman
No es necesario -k1 -nordenar, ya que la salida de awk rand()es un decimal entre 0 y 1 y porque lo único que importa es que se reordena de alguna manera. -k1podría ayudar a acelerarlo ignorando el resto de la línea, aunque la salida de rand () debería ser lo suficientemente única como para hacer un cortocircuito en la comparación.
bonsaiviking
@ ghostdog74: La mayoría de los llamados usos inútiles de cat son realmente útiles para ser coherentes entre los comandos canalizados y no. Es mejor mantener el cat filename |(o < filename |) que recordar cómo cada programa toma la entrada del archivo (o no).
Bien hecho, pero en la práctica mucho más lento que la propia respuesta del OP , que se combina awkcon sorty cut. Para no más de varios miles de líneas, no hace mucha diferencia, pero con un mayor número de líneas es importante (el umbral depende de la awkimplementación utilizada). Una ligera simplificación sería reemplazar líneas while (1){y if (e==d) {break}con while (e<d).
El "inconveniente" no es específico de Python. Los períodos de PRNG finitos podrían solucionarse volviendo a sembrar PRNG con entropía del sistema como lo /dev/urandomhace. Para utilizarlo desde Python: random.SystemRandom().shuffle(L).
jfs
¿la unión () no necesita estar en '\ n' para que las líneas se impriman cada una por su cuenta?
eleg
@elig: No, porque .readLines()devuelve las líneas con una nueva línea final.
Esto debería funcionar en casi cualquier UNIX. Probado en Linux, Solaris y HP-UX.
Actualizar:
Tenga en cuenta que los ceros a la izquierda ( %06d) y la rand()multiplicación hacen que funcione correctamente también en sistemas donde sortno se entienden los números. Se puede ordenar por orden lexicográfico (también conocido como comparación de cadena normal).
Buena idea empaquetar la propia respuesta del OP como una función; si agrega "$@", también funcionará con archivos como entrada. No hay razón para multiplicar rand(), porque sort -nes capaz de ordenar fracciones decimales. Sin embargo, es una buena idea controlar awkel formato de salida, ya que con el formato predeterminado %.6g, rand()generará un número ocasional en notación exponencial . Si bien barajar hasta 1 millón de líneas es suficiente en la práctica, es fácil admitir más líneas sin pagar una gran penalización de rendimiento; por ej %.17f.
mklement0
1
@ mklement0 No noté que los OP respondieron mientras escribía el mío. rand () se multiplica por 10e6 para que funcione con Solaris o hpux, por lo que recuerdo. Buena idea con "$ @"
Michał Šrajer
1
Gracias; quizás podría agregar esta justificación de la multiplicación a la respuesta misma; generalmente, según POSIX, sortdebería poder manejar fracciones decimales (incluso con miles de separadores, como acabo de notar).
Buena cosa; Si lo usa puts ARGF.readlines.shuffle, puede hacer que funcione con entrada de stdin y argumentos de nombre de archivo.
mklement0
Aún más corto ruby -e 'puts $<.sort_by{rand}': ARGF ya es enumerable, por lo que podemos barajar las líneas clasificándolas por valores aleatorios.
akuhn
6
Un delineador para Python basado en la respuesta de scai , pero a) toma stdin, b) hace que el resultado sea repetible con seed, c) selecciona solo 200 de todas las líneas.
Este es un script de Python que guardé como rand.py en mi carpeta de inicio:
#!/bin/python
import sys
import random
if __name__ =='__main__':
with open(sys.argv[1],'r') as f:
flist = f.readlines()
random.shuffle(flist)for line in flist:
print line.strip()
En Mac OSX sort -Ry shufno están disponibles, puede alias esto en su bash_profile como:
Si, como yo, viniste aquí para buscar una alternativa shufpara macOS, úsala randomize-lines.
Instale el randomize-linespaquete (homebrew), que tiene un rlcomando que tiene una funcionalidad similar a shuf.
brew install randomize-lines
Usage: rl [OPTION]...[FILE]...Randomize the lines of a file (or stdin).-c,--count=N select N lines from the file
-r,--reselect lines may be selected multiple times
-o,--output=FILE
send output to file
-d,--delimiter=DELIM
specify line delimiter (one character)-0,--null set line delimiter to null character
(useful with find -print0)-n,--line-number
print line number with output lines
-q,--quiet,--silent
do not output any errors or warnings
-h,--help display this help and exit
-V,--version output version information and exit
Atractivamente simple, pero a menos que Java VM deba iniciarse de todos modos, ese costo de inicio es considerable; tampoco funciona bien con recuentos de líneas grandes.
mklement0
1
Esta función bash tiene una dependencia mínima (solo sort y bash):
Buena solución bash que es paralela a la awksolución asistida por el OP , pero el rendimiento será un problema con una entrada más grande; el uso de un solo $RANDOMvalor baraja correctamente solo hasta 32.768 líneas de entrada; Si bien podría extender ese rango, probablemente no valga la pena: por ejemplo, en mi máquina, ejecutar su script en 32.768 líneas de entrada cortas toma aproximadamente 1 segundo, que es aproximadamente 150 veces más que la ejecución shuf, y aproximadamente 10-15 veces mientras dure la awksolución asistida por el OP . Si puede confiar en sortestar presente, también awkdebería estar allí.
mklement0
0
En Windows, puede probar este archivo por lotes para ayudarlo a barajar sus datos.txt. El uso del código de lote es
C:\> type list.txt | shuffle.bat > maclist_temp.txt
Después de emitir este comando, maclist_temp.txt contendrá una lista aleatoria de líneas.
Respuestas:
Puedes usar
shuf
. Al menos en algunos sistemas (no parece estar en POSIX).Como señaló jleedev:
sort -R
también podría ser una opción. En algunos sistemas al menos; Bueno, te haces una idea. Se ha señalado quesort -R
realmente no se baraja, sino que clasifica los elementos según su valor hash.[Nota del editor:
sort -R
casi se baraja, excepto que las líneas duplicadas / las claves de clasificación siempre terminan una al lado de la otra . En otras palabras: solo con líneas / teclas de entrada únicas es una verdadera combinación aleatoria. Si bien es cierto que el orden de salida está determinado por los valores hash , la aleatoriedad proviene de elegir una función hash aleatoria ; consulte el manual .]fuente
shuf
ysort -R
difieren ligeramente, porquesort -R
ordena aleatoriamente los elementos según el hash de ellos, es decir,sort -R
juntará los elementos repetidos, mientrasshuf
baraja todos los elementos aleatoriamente.brew install coreutils
luego usegshuf ...
(:sort -R
yshuf
debería ser visto como completamente diferente.sort -R
Es determinista. Si lo llama dos veces en diferentes momentos en la misma entrada, obtendrá la misma respuesta.shuf
, por otro lado, produce una salida aleatoria, por lo que probablemente dará una salida diferente en la misma entrada.Perl one-liner sería una versión simple de la solución de Maxim
fuente
\n
; sí, eso\n
debe estar presente, y generalmente lo está , de lo contrario obtendrá lo que describe.<STDIN>
con<>
, por lo que la solución también funciona con la entrada de archivos .Esta respuesta complementa las muchas excelentes respuestas existentes de las siguientes maneras:
Las respuestas existentes se agrupan en funciones de shell flexibles :
stdin
entrada, sino también argumentos de nombre de archivoSIGPIPE
de la manera habitual (terminación silenciosa con código de salida141
), en lugar de romperse ruidosamente. Esto es importante cuando se canaliza la salida de la función a una tubería que se cierra temprano, como cuando se canaliza ahead
.Se realiza una comparación de rendimiento .
awk
,sort
ycut
, adaptada de la propia respuesta del OP :Consulte la sección inferior para obtener una versión de Windows de esta función.
Comparación de rendimiento:
Nota: Estos números se obtuvieron en un iMac de finales de 2012 con Intel Core i5 de 3.2 GHz y una unidad Fusion, con OSX 10.10.3. Si bien los tiempos variarán con el sistema operativo utilizado, las especificaciones de la máquina, la
awk
implementación utilizada (por ejemplo, laawk
versión BSD utilizada en OSX suele ser más lenta que GNUawk
y especialmentemawk
), esto debería proporcionar una sensación general de rendimiento relativo .El archivo de entrada es un archivo de 1 millón de líneas producido con
seq -f 'line %.0f' 1000000
.Los tiempos se enumeran en orden ascendente (el más rápido primero):
shuf
0.090s
0.289s
0.589s
1.342s
con Python 2.7.6;2.407s
(!) con Python 3.4.2awk
+sort
+cut
3.003s
con BSDawk
;2.388s
con GNUawk
(4.1.1);1.811s
conmawk
(1.3.4);Para una mayor comparación, las soluciones no se empaquetan como las funciones anteriores:
sort -R
(no es una combinación aleatoria verdadera si hay líneas de entrada duplicadas)10.661s
- asignar más memoria no parece hacer la diferencia24.229s
bash
bucles +sort
32.593s
Conclusiones :
shuf
, si puede , es el más rápido con diferencia.awk
+ compatible con POSIX como último recursosort
cut
; el queawk
la aplicación utiliza asuntos (mawk
es más rápido que GNUawk
, BSDawk
es más lento).sort -R
,bash
bucles, y Scala.Versiones de Windows de la solución Python (el código de Python es idéntico, excepto por las variaciones en las citas y la eliminación de las declaraciones relacionadas con la señal, que no son compatibles con Windows):
$OutputEncoding
si desea enviar caracteres no ASCII a través de la canalización):Tenga en cuenta que PowerShell puede barajar de forma nativa a través de su
Get-Random
cmdlet (aunque el rendimiento puede ser un problema); p.ej:Get-Content someFile.txt | Get-Random -Count ([int]::MaxValue)
cmd.exe
(un archivo por lotes):Guardar en archivo
shuf.cmd
, por ejemplo:fuente
python -c "import sys, random; lines = [x for x in sys.stdin.read().splitlines()] ; random.shuffle(lines); print(\"\n\".join([line for line in lines]));"
from signal import signal, SIGPIPE, SIG_DFL; signal(SIGPIPE, SIG_DFL);
de la solución original es suficiente y conserva la flexibilidad de poder también pasar argumentos de nombre de archivo ; no es necesario cambiar nada más (excepto las citas). Consulte la nueva sección que he agregado en fondo.Utilizo un pequeño script en perl, al que llamo "sin ordenar":
También tengo una versión delimitada por NULL, llamada "unsort0" ... útil para usar con find -print0 y así sucesivamente.
PD: Votado como 'shuf' también, no tenía idea de que estaba allí en coreutils en estos días ... lo anterior aún puede ser útil si sus sistemas no tienen 'shuf'.
fuente
<STDIN>
con<>
para que la solución funcione con la entrada de archivos también.Aquí hay un primer intento que es fácil para el codificador pero difícil para la CPU, que antepone un número aleatorio a cada línea, los ordena y luego elimina el número aleatorio de cada línea. En efecto, las líneas se ordenan al azar:
fuente
head myfile | awk ...
. Entonces solo lo cambio a gato; por eso lo dejaron allí.-k1 -n
ordenar, ya que la salida de awkrand()
es un decimal entre 0 y 1 y porque lo único que importa es que se reordena de alguna manera.-k1
podría ayudar a acelerarlo ignorando el resto de la línea, aunque la salida de rand () debería ser lo suficientemente única como para hacer un cortocircuito en la comparación.cat filename |
(o< filename |
) que recordar cómo cada programa toma la entrada del archivo (o no).aquí hay un script awk
salida
fuente
awk
consort
ycut
. Para no más de varios miles de líneas, no hace mucha diferencia, pero con un mayor número de líneas es importante (el umbral depende de laawk
implementación utilizada). Una ligera simplificación sería reemplazar líneaswhile (1){
yif (e==d) {break}
conwhile (e<d)
.Una línea para python:
Y para imprimir solo una sola línea aleatoria:
Pero vea esta publicación para conocer los inconvenientes de Python
random.shuffle()
. No funcionará bien con muchos (más de 2080) elementos.fuente
/dev/urandom
hace. Para utilizarlo desde Python:random.SystemRandom().shuffle(L)
..readLines()
devuelve las líneas con una nueva línea final.La función simple basada en awk hará el trabajo:
uso:
Esto debería funcionar en casi cualquier UNIX. Probado en Linux, Solaris y HP-UX.
Actualizar:
Tenga en cuenta que los ceros a la izquierda (
%06d
) y larand()
multiplicación hacen que funcione correctamente también en sistemas dondesort
no se entienden los números. Se puede ordenar por orden lexicográfico (también conocido como comparación de cadena normal).fuente
"$@"
, también funcionará con archivos como entrada. No hay razón para multiplicarrand()
, porquesort -n
es capaz de ordenar fracciones decimales. Sin embargo, es una buena idea controlarawk
el formato de salida, ya que con el formato predeterminado%.6g
,rand()
generará un número ocasional en notación exponencial . Si bien barajar hasta 1 millón de líneas es suficiente en la práctica, es fácil admitir más líneas sin pagar una gran penalización de rendimiento; por ej%.17f
.sort
debería poder manejar fracciones decimales (incluso con miles de separadores, como acabo de notar).Ruby FTW:
fuente
puts ARGF.readlines.shuffle
, puede hacer que funcione con entrada de stdin y argumentos de nombre de archivo.ruby -e 'puts $<.sort_by{rand}'
: ARGF ya es enumerable, por lo que podemos barajar las líneas clasificándolas por valores aleatorios.Un delineador para Python basado en la respuesta de scai , pero a) toma stdin, b) hace que el resultado sea repetible con seed, c) selecciona solo 200 de todas las líneas.
fuente
Una forma simple e intuitiva sería usar
shuf
.Ejemplo:
Asumir
words.txt
como:Para barajar las líneas, haga:
que arrojaría las líneas barajadas a la salida estándar ; Entonces, debe canalizarlo a un archivo de salida como:
Una ejecución de este tipo podría producir:
fuente
Tenemos un paquete para hacer el trabajo:
Ejemplo:
Cree una lista ordenada de números y guárdela en 1000.txt:
para barajarlo, simplemente use
fuente
Este es un script de Python que guardé como rand.py en mi carpeta de inicio:
En Mac OSX
sort -R
yshuf
no están disponibles, puede alias esto en su bash_profile como:fuente
Si, como yo, viniste aquí para buscar una alternativa
shuf
para macOS, úsalarandomize-lines
.Instale el
randomize-lines
paquete (homebrew), que tiene unrl
comando que tiene una funcionalidad similar ashuf
.brew install randomize-lines
fuente
brew install coreutils
proporciona elshuf
binario comogshuf
.Si tiene instalado Scala, aquí hay una línea para mezclar la entrada:
fuente
Esta función bash tiene una dependencia mínima (solo sort y bash):
fuente
awk
solución asistida por el OP , pero el rendimiento será un problema con una entrada más grande; el uso de un solo$RANDOM
valor baraja correctamente solo hasta 32.768 líneas de entrada; Si bien podría extender ese rango, probablemente no valga la pena: por ejemplo, en mi máquina, ejecutar su script en 32.768 líneas de entrada cortas toma aproximadamente 1 segundo, que es aproximadamente 150 veces más que la ejecuciónshuf
, y aproximadamente 10-15 veces mientras dure laawk
solución asistida por el OP . Si puede confiar ensort
estar presente, tambiénawk
debería estar allí.En Windows, puede probar este archivo por lotes para ayudarlo a barajar sus datos.txt. El uso del código de lote es
Después de emitir este comando, maclist_temp.txt contendrá una lista aleatoria de líneas.
Espero que esto ayude.
fuente
No mencionado hasta el momento:
El
unsort
util. Sintaxis (algo orientada a la lista de reproducción):msort
puede barajarse por línea, pero generalmente es exagerado:fuente
Otra
awk
variante:fuente