从类似 XKCD 的密码列表中生成四个随机单词

从类似 XKCD 的密码列表中生成四个随机单词

首先,我们知道如何从 txt 文件中输出随机行:

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

但是我们需要一个通用的解决方案(perl通常安装在每个类unix操作系统上)来从txt文件中输出4个随机单词,我们该怎么做呢?

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

“...”代表许多其他单词。

示例输出(它们之间没有换行符,但末尾需要一个 unix 换行符,空格应将它们分隔开):

$ perl SOMEMAGIC words.txt
gamma alpha delta beta
$

仅使用 perl,这是最短的解决方案(oneliner)。

它将用作人类难忘的密码生成器:https://xkcd.com/936/

因为 afaik perl 足够好,可以被命名为“随机生成器”。

具有 32768 个唯一行的常见英语单词表示例:https://pastebin.ubuntu.com/23726760/

答案1

Perl 实际上并不是一个很好的工具,因为您需要第三方库来安全地生成随机数。默认随机数生成器(rand或使用相同来源的任何其他内容,例如List::Util::shuffle)不适合与安全相关的任何内容。如果你想使用 Perl,请安装数学::随机::安全(及其依赖项)(perl -MCPAN -eshell并运行install Math::Random::Secure)。

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

我建议改用Python。如今,它与 Perl 一样常见,而且它的标准库更加全面。是的,代码较长,但短代码本身并不是质量的标志。

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

以更具可读性的多行形式:

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

或者,如果您有非古董 GNU coreutils(非嵌入式 Linux 和 Cygwin 上的情况),您可以使用shuf公用事业。您需要通过选项传递一个安全随机生成器--random-source

shuf --random-source=/dev/urandom -r -n 4 words.txt

答案2

听起来你不是反对对于非 Perl 解决方案,您只需要能够在大多数系统上运行的东西。在这种情况下,以下仅使用 GNU 核心实用程序:

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

shuf根据 Gilles 的建议修改为使用:

shuf -n 4 -r words.txt | paste -s -d' '

答案3

(忽略@Gilles提到的安全问题)

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

或者如果你喜欢驼峰命名法...

 perl -0nE '@a=split; say map{ ucfirst $a[rand @a] } 1..4'

相关内容