Mi script produce el mismo resultado cuando uso $ RANDOM

8

Estoy tratando de imprimir una npalabra de letra aleatoria , donde ingreso ndesde la línea de comando, pero por alguna razón mi script me da la misma respuesta cada vez que uso el mismo valor para n.

#!/bin/bash                                                                                                                                       
num=$1
egrep "^.{$num}$" /usr/share/dict/words | head -n $RANDOM| tail -n 1

Estoy llamando a mi script como:

$ bash var3.sh 5
étude             # always the same output when using 5 

$ bash var3.sh 3
zoo               # always the same output when using 3

donde var3.shestá el nombre de mi script y 5 es la longitud de la palabra que quiero imprimir al azar.

¿Cómo consigo que imprima una palabra verdaderamente al azar?

Karan Singh
fuente
3
$RANDOMes bastante probable que sea mayor que el número de palabras n- letter para la mayoría de los valores de n (95.7% del tiempo para n = 3 para mí).
Michael Homer
¿Está buscando imprimir una palabra al azar por completo, incluso si no es una palabra o imprimirla al azar desde el dict?
iZodiac
Si su tarea está relacionada con la seguridad (por ejemplo, para crear una contraseña), debe usar una herramienta creada para esa tarea. De lo contrario, es posible usar shufo sort -Rcomo se sugiere en las respuestas. También puede usar $RANDOM, pero de una manera más avanzada. Todas estas herramientas producen resultados que pueden predecirse (no son realmente aleatorios), pero son lo suficientemente rápidos y buenos para muchos propósitos.
sudodus
1
Tal vez usan este método (referencia obligatoria XKCD)
molnarm

Respuestas:

20

No lo hace. Pero $ RANDOM devuelve números grandes (entre 0 y 32767) que, especialmente para palabras de longitud limitada, muestra el mismo resultado, ya que la headporción probablemente devuelve todos los resultados del grep (para 3, solo hay 819 coincidencias en mi /usr/share/dict/words).

Una mejor solución podría ser barajar los resultados:

egrep "^.{$num}$" /usr/share/dict/words | sort -R | tail -n 1

donde -Rsignifica --random-sort(una sortextensión GNU ).

Jakub Lucký
fuente
16
¿Por qué tail? Eso tenía sentido en la secuencia de comandos de OP, pero como estás barajando, podrías usarlo head, y luego sortser capaz de detectar la tubería rota y no molestarte en barajar el resto de las líneas.
Peter Taylor
@PeterTaylor probablemente un buen consejo. Usar cola es solo un hábito mío ... Al final, probablemente preferiría aún más shuf -n1, que es una pipa menos ...
Jakub Lucký
19

Un método simple para imprimir una palabra arbitraria num -letter utiliza shuf:

egrep "^.{$num}$" /usr/share/dict | shuf -n1

El shufcomando genera una permutación aleatoria de la entrada y el -n1indicador le dice que solo muestre el primer elemento de este resultado.

zorro
fuente
3
o grep -Ex ".{$num}". O awk 'length == n' n="$num"'.
Stéphane Chazelas
5

Como otros han señalado, el problema principal con su código es que la $RANDOMmayoría de las veces será un valor mucho mayor que el número de palabras de cierta longitud.

Usando awksolo:

$ awk -v len="$num" 'length == len { word[i++]=$0 }
                     END { print word[int(i*rand())] }' /usr/share/dict/words
Bosniac

El programa lee en todas las líneas del archivo dado que son de cierta longitud. Estos se almacenan en la matriz words.

Al final, se selecciona e imprime un elemento aleatorio de esta matriz.

Kusalananda
fuente