Quiero reorganización de las líneas de un archivo de texto al azar y crear un nuevo archivo. El archivo puede tener varios miles de líneas.

¿Cómo puedo hacer que con cat, awk, cut, etc?

  • Duplicado de stackoverflow.com/questions/886237/…
  • Sí, hay algunas otras buenas respuestas en que la pregunta original así.
  • así, fueron a tomar una wpa lista de palabras? (sólo una estimación aleatoria)

19 Comentarios

  1. 338

    Puede utilizar shuf. En algunos sistemas, al menos, (no parece ser en POSIX).

    Como jleedev señaló: sort -R también podría ser una opción. En algunos sistemas, al menos; así, se obtiene la imagen. Se ha señalado que sort -R realmente no aleatorio, pero en lugar de ordenar los elementos de acuerdo a su valor hash.

    [nota del Editor: sort -R casi baraja, excepto que duplicado de las líneas o criterios de ordenación que siempre terminan uno al lado del otro. En otras palabras: sólo con único líneas de entrada /claves es que es una verdadera shuffle. Si bien es cierto que el orden de salida es determinado por valores hash, la aleatoriedad trata de elegir una al azar hash función – ver manual.]

    • Genial, yo no sabía acerca de shuf. Parece que es parte de coreutils, pero la versión que he instalado en mi servidor no tiene shuf.
    • Sí, parece ser GNU-sólo cosas, por desgracia. Nada de ello en POSIX.
    • Es curioso que GNU coreutils tiene tanto shuf y sort -R.
    • Tenga en cuenta que shuf es probablemente una de las más versión correcta de lo que estamos tratando de hacer. La lectura de este artículo sobre por qué arrastrando los pies, ingenuamente, puede ser una mala idea: codinghorror.com/blog/2007/12/the-danger-of-naivete.html
    • conradlee: Tanto sort -R y shuf debe hacer razonablemente bien shuffle. Si no, bueno, entonces los autores eran imbéciles. En ninguna parte he dicho nada de revolver ingenuamente.
    • shuf y sort -R difieren ligeramente, porque sort -R al azar ordena los elementos según hash de ellos, que es, sort -R pondrá los elementos repetidos juntos, mientras que shuf baraja todos los elementos al azar.
    • +1 para shuf — Se corrió mucho más rápido que en mi caso (transposición de 60gb archivo tomó tal vez 20 minutos con shuf vs sort -R se estaba ejecutando durante 1.5 horas antes de que me mató)
    • El rl comando también está disponible en el randomize-lines paquete, al menos en Ubuntu.
    • El autor recomienda el uso de shuf.
    • Para los usuarios de OS X: brew install coreutils, a continuación, utilizar gshuf ... (:
    • sort -R y shuf debe ser visto como algo completamente diferente. sort -R es determinista. Si usted lo llama dos veces a distintas horas y en la misma entrada obtendrá la misma respuesta. shuf, por otro lado, produce aleatorizado salida, por lo que es probable la salida diferente en la misma entrada.
    • Eso no es correcto. «sort-R» utiliza un diferentes al azar hash de la clave cada vez que se invoca, por lo que produce un resultado diferente cada vez.
    • FreeBSD tiene sysutils/coreutils en los Puertos/pkg. Uso gshuf. FYI.
    • Para aclarar el sort -R problema: los resultados son ordenada al azar general, excepto para duplicar las líneas de (teclas), que siempre uno al lado del otro. La razón es que la ordenación se basa en hash de las líneas de entrada (teclado) generados por un elegidas al azar de una función hash.
    • Nota sobre la aleatoriedad: por la GNU docs, «de forma predeterminada, estos comandos de uso interno generador pseudoaleatorio inicializado por una pequeña cantidad de entropía, pero puede ser dirigida para utilizar una fuente externa con el –random-source=archivo de opción».
    • Supongo sort -R sería más lento que shuf ya que la clasificación es un O(n logn) operación, y shuffeling es O(n)?
    • Eso sería asumir que ambos programas son óptimas (o de igual manera subóptima)… pero shuf es, de hecho, alrededor de 10 veces más rápido que sort -R de 100.000 líneas cortas en mis pruebas. (Un inciso, shuf -n <num> no ofrece notables mejoras en el rendimiento sobre shuf | head -n <num>, lo que sugiere que no es manejado de manera óptima.)

  2. 81

    Perl de una línea puede ser una simple versión de Maxim solución

    perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' < myfile
    • Yo con un alias de esta reorganización en OS X. Gracias!
    • Esta fue la única secuencia de comandos de esta página que devuelve VERDADERO líneas al azar. Otros awk soluciones a menudo se imprimen duplicado de salida.
    • Pero tenga cuidado, porque en el cabo se pierde una línea 🙂 sólo se unió con otra línea 🙂
    • Supongo que usted está hablando acerca de una entrada sin un final \n; sí, que \n debe estar presente – y, por lo general es – de lo contrario, usted conseguirá lo que usted describe.
    • Maravillosamente concisa. Me sugieren cambiar <STDIN> con <>, por lo que la solución funciona con el aporte de archivos también.
    • Las otras respuestas sugieren utilidades que usted puede o no puede ya tiene en su sistema. Todo el mundo tiene perl, aunque (y si no, entonces necesitas algo va a requerir en algún momento).

  3. 57

    Esta respuesta complementa muchos de los grandes de las respuestas de las siguientes maneras:

    • Las respuestas existentes son empaquetados en flexible funciones de shell:

      • Las funciones tomar no sólo stdin de entrada, pero también como alternativa nombre de archivo argumentos
      • Las funciones tomar pasos adicionales para manejar SIGPIPE en la forma habitual (tranquilo terminación con código de salida 141), como contraposición a romper ruidosamente. Esto es importante cuando la tubería de la función de salida de una tubería que se cerró antes de tiempo, como cuando la tubería para head.
    • Un comparación del rendimiento de está hecho.


    • Compatible con POSIX función que se basa en awk, sort, y cut, adaptado de la OP propia respuesta:
    shuf() { awk 'BEGIN {srand(); OFMT="%.17f"} {print rand(), $0}' "[email protected]" |
                   sort -k1,1n | cut -d ' ' -f2-; }
    shuf() { perl -MList::Util=shuffle -e 'print shuffle(<>);' "[email protected]"; }
    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))
    ' "[email protected]"; }
    shuf() { ruby -e 'Signal.trap("SIGPIPE", "SYSTEM_DEFAULT");
                         puts ARGF.readlines.shuffle' "[email protected]"; }

    Comparación de rendimiento:

    Nota: Estos números fueron obtenidos en una tarde-2012 iMac con 3.2 GHz Intel Core i5 y una Unidad Fusion drive, que ejecutan OS x 10.10.3. Mientras que los tiempos varían con el sistema operativo utilizado, máquina especificaciones, awk aplicación utiliza (por ejemplo, el BSD awk versión utilizada en OSX es generalmente más lento que el de GNU awk y especialmente mawk), esto debería proporcionar un sentido general de relativa rendimiento.

    De entrada archivo es un de 1 millón de líneas de archivo producido con seq -f 'line %.0f' 1000000.

    Veces se enumeran en orden ascendente (más rápido de la primera):

    • shuf
      • 0.090s
    • Ruby 2.0.0
      • 0.289s
    • Perl 5.18.2
      • 0.589s
    • Python
      • 1.342s con Python 2.7.6; 2.407s(!) con Python 3.4.2
    • awk + sort + cut
      • 3.003s con BSD awk; 2.388s con GNU awk (4.1.1); 1.811s con mawk (1.3.4);

    Para su posterior comparación, las soluciones no se empaqueta como funciones anteriores:

    • sort -R (no un verdadero shuffle si hay duplicados líneas de entrada)
      • 10.661s – asignar más memoria no parece hacer una diferencia
    • Scala
      • 24.229s
    • bash bucles + sort
      • 32.593s

    Conclusiones:

    • Uso shuf, si usted puede – es el más rápido con diferencia.
    • Ruby hace bien, seguido por Perl.
    • Python es notablemente más lento que el de Ruby y Perl, y, comparando las versiones de Python, 2.7.6 es un poco más rápido que 3.4.1
    • Utilizar el POSIX awk + sort + cut combinado como un último recurso; que awk implementación de utilizar los asuntos (mawk es más rápido que el de GNU awk, BSD awk es más lento).
    • Permanecer lejos de sort -R, bash bucles, y de la Scala.
  4. 27

    Yo uso un pequeño script en perl, que yo llamo «desordenar»:

    #!/usr/bin/perl
    use List::Util 'shuffle';
    @list = <STDIN>;
    print shuffle(@list);

    Yo también tengo un NULL-delimitado versión, llamada «unsort0» … a mano para su uso con encontrar -print0 y así sucesivamente.

    PD: Votado arriba «shuf» demasiado, no tenía idea de que estaba allí en coreutils estos días … el de arriba aún puede ser útil si su sistema no tiene ‘shuf’.

    • bueno, RHEL 5.6 no tiene shuf (
    • Muy bien hecho; me sugieren cambiar <STDIN> con <> con el fin de hacer que la solución de trabajo con el aporte de archivos también.
  5. 20

    Aquí es un primer intento que es fácil en la programacion, pero difícil en la CPU que se antepone un número aleatorio para cada línea, los ordena y, a continuación, elimina el número aleatorio a partir de cada línea. En efecto, las líneas se ordenan al azar:

    cat myfile | awk 'BEGIN{srand();}{print rand()"\t"$0}' | sort -k1 -n | cut -f2- > myfile.shuffled
    • UUOC. pasar el archivo awk sí mismo.
    • A la derecha, yo depuración con head myfile | awk .... Luego me cambie a la cat; por eso se quedó allí.
    • No necesita -k1 -n para ordenar, ya que la salida de awk rand() es un decimal entre 0 y 1, y porque todo lo que importa es que se pone a ordenar de alguna manera. -k1 podría ayudar a acelerar ignorando el resto de la línea, a pesar de la salida de la función rand() debe ser único suficiente para corto circuito en la comparación.
    • La mayoría de los llamados usos inútiles de gato son realmente útiles para ser coherentes entre hilo de comandos y no. Mejor mantener el cat filename | (o < filename |) que recuerda cómo cada uno de los programa de toma de entrada de archivo (o no).
    • shuf() { awk ‘BEGIN{srand()}{print rand()»\t»$0}’ «[email protected]» | especie | cut-f2- ;}
    • es redundante, porque todavía se ordena la línea de como un todo, porque no dejar campo se especifica; verdaderamente límite de la clasificación para el primer campo, -k1,1 es necesario. Sin embargo, el uso de -n velocidades de hasta ordenación notablemente. Por lo tanto, usted debe utilizar -k1,1 -n (a ser explícito) o, aprovechando el hecho de que la clave de ordenación es el primer campo y que sort utiliza más el prefijo correspondiente al detectar números, sólo -n.

  6. 16

    he aquí un script awk

    awk 'BEGIN{srand() }
    { lines[++d]=$0 }
    END{
        while (1){
        if (e==d) {break}
            RANDOM = int(1 + rand() * d)
            if ( RANDOM in lines  ){
                print lines[RANDOM]
                delete lines[RANDOM]
                ++e
            }
        }
    }' file

    salida

    $ cat file
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    $ ./shell.sh
    7
    5
    10
    9
    6
    8
    2
    1
    3
    4
    • Muy bien hecho, pero en la práctica mucho más lento que el de el OP de la propia respuesta, que combina awk con sort y cut. Para no más de varios miles de línea de no hacer una gran diferencia, pero con mayor línea de cuenta lo que importa (el umbral depende de la awk implementación utilizada). Una ligera simplificación sería sustituir las líneas de while (1){ y if (e==d) {break} con while (e<d).
  7. 11

    Un one-liner para python:

    python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," myFile

    Y para la impresión de un solo aleatoria de la línea:

    python -c "import random, sys; print random.choice(open(sys.argv[1]).readlines())," myFile

    Pero ver este post las desventajas de python random.shuffle(). No funciona bien con muchos (más de 2080) elementos.

    • el «inconveniente» es que no es específica a Python. Finito PRNG períodos pueden ser workarounded por la resiembra de PRNG con la entropía del sistema como /dev/urandom hace. Para utilizar desde Python: random.SystemRandom().shuffle(L).
  8. 9

    Simple awk basado en la función de realizar el trabajo:

    shuffle() { 
        awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8-
    }

    uso:

    any_command | shuffle

    Esto debería funcionar en casi cualquier UNIX. Probado en Linux, Solaris y HP-UX.

    Actualización:

    Nota, que los ceros a la izquierda (%06d) y rand() multiplicación se hace para que funcione correctamente también en sistemas donde sort no entiende de números. Puede ser ordenado a través de la orden lexicográfico (un.k.una. normal de la comparación de cadenas).

    • Buena idea paquete de la OP propia respuesta como una función; si anexa "[email protected]", que también va a trabajar con archivos como entrada. No hay ninguna razón para multiplicar rand(), porque sort -n es capaz de clasificar las fracciones decimales. Es, sin embargo, una buena idea para controlar awk‘s el formato de salida, porque con el formato predeterminado, %.6g, rand() de salida será de la ocasional número en exponencial la notación. Mientras arrastrando los pies hasta 1 millón de líneas que podría decirse que es suficiente en la práctica, es fácil de soporte de las líneas más sin tener que pagar mucho de una penalización de rendimiento; por ejemplo,%.17f.
    • Yo no me di cuenta OPs respuesta al escribir la mía. rand() se multiplica por 10e6 a hacer el trabajo con solaris o hpux tipo tan lejos como puedo recordar. Buena idea con «[email protected]»
    • Tengo, gracias; tal vez se podría agregar este justificación de la multiplicación a la respuesta en sí misma; por lo general, de acuerdo con POSIX, sort debe ser capaz de manejar las fracciones decimales (incluso con separadores de miles, como lo he notado).
  9. 7

    Ruby FTW:

    ls | ruby -e 'puts STDIN.readlines.shuffle'
    • Grandes cosas; Si utiliza puts ARGF.readlines.shuffle, usted puede hacer el trabajo con ambos stdin de entrada y el nombre de los argumentos.
    • Aún más corto ruby -e 'puts $<.sort_by{rand}' — ARGF es ya un enumerable, por lo que podemos barajar las líneas a través de la clasificación por valores aleatorios.
  10. 6

    Uno forro para Python basado en scai de la respuesta, pero a) toma de stdin, b) hace que el resultado repetible con semilla, c) recoge sólo 200 de todas las líneas.

    $ cat file | python -c "import random, sys; 
      random.seed(100); print ''.join(random.sample(sys.stdin.readlines(), 200))," \
      > 200lines.txt
  11. 5

    Una manera sencilla e intuitiva sería el uso de shuf.

    Ejemplo:

    Asumir words.txt como:

    the
    an
    linux
    ubuntu
    life
    good
    breeze

    La reorganización de las líneas, hacer:

    $ shuf words.txt

    que sería lanza el barajan líneas de salida estándar; Así que, has a tubo a un archivo de salida como:

    $ shuf words.txt > shuffled_words.txt

    Uno de esos shuffle ejecutar podría producir:

    breeze
    the
    linux
    an
    ubuntu
    good
    life
  12. 4

    Tenemos un paquete para hacer el mismo trabajo:

    sudo apt-get install randomize-lines

    Ejemplo:

    Crear una lista ordenada de números, y los guarde 1000.txt:

    seq 1000 > 1000.txt

    shuffle, simplemente uso

    rl 1000.txt
  13. 3

    Este es un script de python que me guarda como rand.py en mi casa carpeta:

    #!/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 -R y shuf no están disponibles para que usted pueda alias esta en su bash_profile como:

    alias shuf='python rand.py'
  14. 3

    Si como yo, usted vino aquí a buscar una alternativa a shuf para macOS, a continuación, utilizar randomize-lines.

    Instalar randomize-lines(homebrew) paquete, que tiene un rl comando 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
    • La instalación de Coreutils con brew install coreutils proporciona la shuf binario como gshuf.
  15. 2

    Si usted tiene Scala instalado, he aquí un one-liner reorganización de la entrada:

    ls -1 | scala -e 'for (l <- util.Random.shuffle(io.Source.stdin.getLines.toList)) println(l)'
    • Seductoramente simple, pero a menos que la máquina virtual de Java debe ser iniciado de todos modos, que el costo de inicio es considerable, no funcionan bien con los grandes de la línea de cuenta tampoco.
  16. 1

    Esta función bash tiene la mínima dependencia(sólo tipo y bash):

    shuf() {
    while read -r x;do
        echo $RANDOM$'\x1f'$x
    done | sort |
    while IFS=$'\x1f' read -r x y;do
        echo $y
    done
    }
    • Bonito bash solución que se asemeja a la OP del propio awkasistida solución, pero el rendimiento será un problema con el mayor de entrada; el uso de una sola $RANDOM valor baraja correctamente sólo hasta 32.768 en líneas de entrada; si bien se podría extender el alcance, probablemente no valga la pena: por ejemplo, en mi máquina, ejecute la secuencia de comandos en 32.768 que corta líneas de entrada toma alrededor de 1 segundo, que es de alrededor de 150 veces tan largo como la ejecución de shuf toma, y unos 10-15 veces tan largo como el OP de la propia awkasistida solución toma. Si usted puede confiar en sort estar presente, awk debería ser así.
  17. 0

    De windows que Usted puede tratar de este archivo de proceso por lotes para ayudar a la reorganización de su data.txt El uso de código de lote es

    C:\> type list.txt | shuffle.bat > maclist_temp.txt

    Después de emitir este comando, maclist_temp.txt contendrá un estudio aleatorizado lista de líneas.

    Espero que esto ayude.

    • No funciona para archivos de gran tamaño. Me dio hasta después de 2 horas para 1 millón de+ líneas archivo
  18. 0

    No mencionado hasta el momento:

    1. La desordenar util. Sintaxis (algo orientado a la lista de reproducción):

      unsort [-hvrpncmMsz0l] [--help] [--version] [--random] [--heuristic]
             [--identity] [--filenames[=profile]] [--separator sep] [--concatenate] 
             [--merge] [--merge-random] [--seed integer] [--zero-terminated] [--null] 
             [--linefeed] [file ...]
    2. msort se pueden barajar por línea, pero por lo general es una exageración:

      seq 10 | msort -jq -b -l -n 1 -c r
  19. 0

    Otro awk variante:

    #!/usr/bin/awk -f
    # usage:
    # awk -f randomize_lines.awk lines.txt
    # usage after "chmod +x randomize_lines.awk":
    # randomize_lines.awk lines.txt
    
    BEGIN {
      FS = "\n";
      srand();
    }
    
    {
      lines[ rand()] = $0;
    }
    
    END {
      for( k in lines ){
        print lines[k];
      }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here