Quatro palavras aleatórias de uma lista com Perl!

4

Para começar, sabemos como podemos produzir linhas aleatórias a partir de um arquivo txt:

perl -MList::Util -e 'print List::Util::shuffle <>' words.txt

Mas precisamos de uma solução geral (o perl geralmente é instalado em cada sistema operacional similar ao UNIX) para gerar 4 palavras aleatórias a partir de um arquivo txt. Como podemos fazer isso?

$ cat words.txt
...
alpha
beta
gamma
delta
epsilon
...
$

O "..." representa muitas outras palavras.

Exemplo de saída (sem nova linha entre eles, mas uma nova linha no Unix é necessária no final, espaços devem separá-los):

$ perl SOMEMAGIC words.txt
gamma alpha delta beta
$

Usando apenas perl, a solução mais curta possível (oneliner).

Ele será usado como um gerador de senhas memorizável: link

Como o afaik perl é suficiente para ser chamado de "gerador aleatório".

Exemplo de lista de palavras em inglês comum com 32768 linhas exclusivas: link

    
por halajoe 01.01.2017 / 16:11

3 respostas

4

O Perl não é uma ferramenta tão boa para isso porque você precisa de uma biblioteca de terceiros para gerar números aleatórios com segurança. O gerador de números aleatórios padrão ( rand ou qualquer outra coisa que use a mesma origem, como List::Util::shuffle ) não é adequado para nada relacionado à segurança. Se você quiser usar o Perl, instale Math :: Random :: Secure (e sua dependências) ( perl -MCPAN -eshell e executar install Math::Random::Secure ).

perl -MMath::Random::Secure=rand -l -e '@words = <>; print map $words[rand(@words)], 1..4' words.txt

Sugiro usar o Python. Hoje em dia, é tão comum quanto o Perl, e sua biblioteca padrão é muito melhor arredondada. Sim, o código é mais longo, mas o código curto não é em si um sinal de qualidade.

python -c 'import random, sys; rng = random.SystemRandom(); words = sys.stdin.readlines(); print " ".join([words[rng.randrange(0, len(words))][:-1] for i in xrange(4)])' <words.txt

Em um formulário multilinha mais legível:

import random, sys
rng = random.SystemRandom()
words = sys.stdin.readlines()
print " ".join([words[rng.randrange(0, len(words))][:-1] for i in xrange(4)])

Alternativamente, se você tiver coreutils GNU não antigos, que é o caso de Linux e Cygwin não embutidos, você pode usar o shuf . Você precisa passar um gerador aleatório seguro com a opção --random-source .

shuf --random-source=/dev/urandom -r -n 4 words.txt
    
por 02.01.2017 / 01:58
2

Parece que você não está contra soluções não-Perl, você só quer algo que funcione na maioria dos sistemas. Nesse caso, o seguinte usa apenas os utilitários principais do GNU:

sort -R --random-source=/dev/urandom words.txt | head -n4 | paste -s -d' '

Modificado para usar shuf , com base na sugestão de Gilles:

shuf -n 4 -r words.txt | paste -s -d' '
    
por 01.01.2017 / 23:18
1

(ignorando o problema de segurança mencionado por @Gilles)

 perl -0nE '@a=split; say join(" ", map{ $a[rand @a] } 1..4)'

ou se você gosta do CamelCase ...

 perl -0nE '@a=split; say map{ ucfirst $a[rand @a] } 1..4'
    
por 02.01.2017 / 13:05