Meu script produz a mesma saída ao usar $ RANDOM

8

Estou tentando imprimir uma npalavra de letra aleatória , onde insiro a npartir da própria linha de comando, mas, por alguma razão, meu script está me dando a mesma resposta sempre que usar o mesmo valor para n.

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

Estou chamando meu 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

onde var3.shé o nome do meu script e 5 é o tamanho da palavra que eu quero imprimir aleatoriamente.

Como faço para imprimir uma palavra verdadeiramente aleatória?

Karan Singh
fonte
3
$RANDOMé bem provável que seja maior que o número de palavras com n letras para a maioria dos valores de n (95,7% do tempo para n = 3 para mim).
Michael Homer
Você deseja imprimir uma palavra aleatória completamente, mesmo que não seja uma palavra ou imprimi-la aleatoriamente a partir do ditado?
IZodiac
Se sua tarefa estiver relacionada à segurança (por exemplo, para criar uma senha), você deve usar uma ferramenta criada para essa tarefa. Caso contrário, é possível usar shufou sort -Rconforme sugerido nas respostas. Você também pode usar $RANDOM, mas de uma maneira mais avançada. Todas essas ferramentas produzem resultados que podem ser previstos (eles não são verdadeiramente aleatórios), mas são rápidos e bons o suficiente para muitos propósitos.
sudodus 12/06
1
Talvez eles usam este método (referência XKCD aplicabilidade)
molnarm

Respostas:

20

Não faz. Mas $ RANDOM retorna números grandes (entre 0 e 32767) que, especialmente para palavras de comprimentos limitados, mostram o mesmo resultado, pois a headparte provavelmente retorna todos os resultados do grep (para 3, existem apenas 819 correspondências no meu /usr/share/dict/words).

A melhor solução seria embaralhar os resultados:

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

onde -Rsignifica --random-sort(uma sortextensão GNU ).

Jakub Lucký
fonte
16
Por que tail? Isso fazia sentido no script do OP, mas como você está embaralhando, também pode usar heade, em seguida, sortdeve ser capaz de detectar o cano quebrado e não se incomodar em embaralhar o restante das linhas.
Peter Taylor
@ PeterTaylor provavelmente uma boa dica. Usar cauda é apenas um hábito meu ... No final, eu provavelmente preferiria ainda mais o shuf -n1, que é um cano a menos ...
Jakub Lucký
19

Um método simples para imprimir uma arbitrariedade num -Carta usos da palavra shuf:

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

O shufcomando gera uma permutação aleatória da entrada, e o -n1sinalizador informa para que ele somente produza o primeiro item desse resultado.

Raposa
fonte
3
ou grep -Ex ".{$num}". Or awk 'length == n' n="$num"'.
Stéphane Chazelas
5

Como outros já apontaram, o principal problema do seu código é que, na $RANDOMmaioria das vezes, será um valor muito maior do que o número de palavras de um determinado comprimento.

Usando awkapenas:

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

O programa lê todas as linhas do arquivo fornecido com um determinado comprimento. Estes são armazenados na matriz words.

No final, um elemento aleatório dessa matriz é selecionado e impresso.

Kusalananda
fonte