¿Cómo aleatorizar la salida de seq?

11

Sé que puedo usar seqpara generar una lista aleatoria de números: 1, 2, 3, 4 ...

Quiero poner esos números en un orden aleatorio como 3, 1, 4, 2 ...

Sé que puedo usar shufpara mezclar las líneas de un archivo. Por lo tanto, podría usar seqpara escribir números aleatorios en un archivo y luego usarlos shufpara mezclarlos, o escribir algún tipo de función aleatoria. Pero esto parece innecesariamente complejo. ¿Hay una manera más simple de aleatorizar los elementos en una matriz con un solo comando?

bernie2436
fuente

Respuestas:

16

Simplemente puede canalizar la salida a shuf.

$ seq 100 | shuf

Ejemplo

$ seq 10 | shuf
2
6
4
8
1
3
10
7
9
5

Si desea que la salida sea horizontal, canalícela a paste.

$ seq 10 | shuf | paste - -s -d ' '
1 6 9 3 8 4 10 7 2 5 

$ seq 10 | shuf | paste - -s -d ' '
7 4 6 1 8 3 10 5 9 2 

$ seq 10 | shuf | paste - -s -d ' '
9 8 3 6 1 2 10 4 7 5 

¿Lo quieres con comas en el medio? Cambie el delimitador a paste:

$ seq 10 | shuf | paste - -s -d ','
2,4,9,1,8,7,3,5,10,6
slm
fuente
Pero tienes que formatear de alguna manera para ponerlos en una línea con comas. echo $(seq 10 | shuf)se acerca pero no hace las comas.
mikeserv
Es horizontal antes paste...
mikeserv
@mikeserv: lo cambió.
slm
Si. Ahí tienes. No sabía pasteque hice eso. Gracias por enseñarme Tener un voto a favor.
mikeserv
@mikeserv: sí, lea el sitio mirando el mío, el de Stephane o el de Gilles A usando joiny paste. Esas 2 herramientas son extremadamente poderosas.
slm
3

¿Hay una manera más simple de aleatorizar los elementos en una matriz con un solo comando?

Suponiendo que tiene una matriz de enteros decimales:

arr=(4 8 14 18 24 29 32 37 42)

Puede usar printfy shufpara aleatorizar los elementos de la matriz:

$ arr=($(printf "%d\n" "${arr[@]}" | shuf))
$ echo "${arr[@]}"
4 37 32 14 24 8 29 42 18

(lo anterior supone que no ha modificado $IFS).


Si todo lo que necesita son números aleatorios entre dos enteros, digamos 10y 20, no necesita ningún proceso adicional que no sea shufmediante la -iopción:

$ shuf -i 10-20
12
10
20
14
16
19
13
11
18
17
15

Citando de man shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line
devnull
fuente
Shucks También lo vi, shuf --helppero traté de usarlo shuf -i 1 10sin la intervención -dash., bueno, buen trabajo, tenga mi voto positivo.
mikeserv
2
printf '%s, ' `seq 1 10 | shuf`

Ni siquiera necesitas un forbucle.

SALIDA

7, 3, 4, 10, 2, 9, 1, 8, 5, 6,

Para obtenerlos en una matriz de shell, debe hacer lo siguiente:

( set -- $(seq 1 10 | shuf) ; printf '%s, ' "$@" )

SALIDA

5, 9, 7, 2, 4, 3, 6, 1, 10, 8,

Y luego están en su matriz de shell.

Si los obtiene en la matriz de shell, ni siquiera necesita printf:

( set -- $(seq 1 10 | shuf); IFS=, ; echo "$*" )

SALIDA

9,4,10,3,1,2,7,5,6,8

Por cierto, seqy printfestán hechos el uno para el otro. Por ejemplo, si quiero repetir una cadena 1000 veces?

printf 'a string\n%.0b' `seq 1 1000`

SALIDA

a string

... 999 a stringlíneas después ...

a string

O...

printf 'a string,%.0b' `seq 1 10`

SALIDA

a string,a string,a string,a string,a string,a string,a string,a string,a string,a string,

Quiero ejecutar un comando 39 veces?

printf 'echo "run %d"\n' `seq 1 39` | . /dev/stdin

SALIDA

run 1

... 38 runlíneas después ...

run 39
mikeserv
fuente
1

Puede usar el shufcomando para aleatorizar la salida, por ej.

%> for x in $(seq 1 10 | shuf); do echo -n "$x "; done; echo
4 10 8 7 1 6 3 5 2 9 
margarita
fuente
1

POSIXY, para generar una lista aleatoria de los enteros decimales de mina max:

awk -v min=1 -v max=10 'BEGIN{
  for (i = min; i <= max; i++) a[i] = i
  srand()
  for (i = min; i <= max; i++) {
    j = int(rand() * (max - min + 1)) + min
    tmp = a[i]; a[i] = a[j]; a[j] = tmp
  }
  for (i = min; i <= max; i++) print a[i]
}'

Tenga en cuenta que con muchas implementaciones awk, ejecutar ese comando dos veces en el mismo segundo producirá el mismo resultado (ya que srand()genera el generador pseudoaleatorio en función del tiempo actual).

Stéphane Chazelas
fuente