如何使用Bash从字符串/数组中选择随机字符?

如何使用Bash从字符串/数组中选择随机字符?,bash,random,Bash,Random,我举了一个例子,试图在一组字母中随机生成一个字母(即var=“abcdefghijklmnopqrstuvwxyz”) 我该怎么办: var="abcdefghijklmnopqrstuvwxyz" echo "${var}" 收益率:一些字母 关键是,我正在尝试从我选择的选择中自动生成一个随机字母。它是在数组中还是在字符串中并不重要 var="abcdefghijklmnopqrstuvwxyz" echo "${var:$(( RANDOM % ${#var} )):1}" # pick

我举了一个例子,试图在一组字母中随机生成一个字母(即var=“abcdefghijklmnopqrstuvwxyz”)

我该怎么办:

var="abcdefghijklmnopqrstuvwxyz"

echo "${var}"
收益率:
一些字母

关键是,我正在尝试从我选择的选择中自动生成一个随机字母。它是在数组中还是在字符串中并不重要

var="abcdefghijklmnopqrstuvwxyz"
echo "${var:$(( RANDOM % ${#var} )):1}" # pick a 1 char substring starting at a random position
这是因为:

  • ${var:START:LEN}
    是扩展为
    $var
  • ${#var}
    是一个参数扩展,扩展到字符串变量var的内容长度
  • $(())
    创建一个算术上下文,在该上下文中,假定非数字字符串引用变量名(因此可以使用
    随机
    而不是
    $RANDOM
  • $RANDOM
    每次计算时,它都会扩展为0到32767之间的随机整数
  • $RANDOM%${#var}
    取该随机整数除以名为
    var
    的字符串中的字符数的余数;因此,它将介于0和(长度-
    var
    -1)之间,并且几乎是随机划分的(如果-
    var
    的长度没有平均划分为32768,那么一些字符被选择的几率将比其他字符略高)

因此,
${var:$((RANDOM%${var})):1}
将在每次求值时在字符串中选择一个位置,并扩展到字符串中的单个字符范围。

对于大多数实际情况,的解决方案是前进的方向。但是,如果您的随机角色选择必须是一致的,那么当您想要使用
随机
(请参见下面的解释)时,故事会变得稍微复杂一些。最好的方法是使用
shuf
shuf
生成给定范围的随机排列,并允许您选择第一个数字,如
shuf-i0-25-n1
,以便使用

var="abcdefghijklmnopqrstuvwxyz"
echo ${var:$(shuf -i 0-$((${#var}-1)) -n1):1}
随机变量
random
生成一个介于0和32767之间的伪随机数。这意味着,如果要生成介于
0
n
之间的随机数,则不能使用mod。这里的问题是,第一个
32768%n
数字绘制的几率更高。通过以下脚本可以很容易地看到这一点:

% for i in {0..32767}; do echo $((i%5)); done | sort -g | uniq -c
   6554 0
   6554 1
   6554 2
   6553 3  < smaller change to hit 3
   6553 4  < smaller chance to hit 4
如果要使用
RANDOM
,最好的方法是跳过不需要的值,这可以通过一个简单的
while
循环来实现

var="abcdefghijklmnopqrstuvwxyz"
n=${#var}
idx=32769; while (( idx >= (32768/n)*n )); do idx=$RANDOM; done
char=${var:$idx:1}
注意:您可能会在while循环中被永远卡住

评论:我们不评论
random
背后的随机数生成器有多好。我们所做的只是引用来源中的评论:

源代码bash4.4.18(
variables.c


你也可以用更简洁的方式使用
shuf

基本上,您可以在每一行上将字符串拆分为一个字符,然后按照正常方式使用
shuf

使用
折叠
进行拆分

echo“abcdefghijklmnopqrstuvxyz”| fold-w1 | shuf-n1
使用
grep
进行拆分

echo“abcdefghijklmnopqrstuvxyz”| grep-o.|shuf-n1

数组和字符串是两种不同的数据类型,顺便问一下,它们是shell吗?您还将其标记为
sh
,但如果您需要sh兼容性,则某些仅限bash的技术不可用。堆栈溢出不是一种代码编写服务。请出示你的密码。由于堆栈溢出对您隐藏了关闭原因:寻求调试帮助的问题(“为什么此代码不工作?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:。你说的“变量数组”是什么意思?这根本不是一个数组。如果您在bash中工作,为什么要回滚我的编辑,删除
sh
标记?(类似地,
terminal
标记仅用于有关终端的问题-这不是-
linux
标记用于特定于linux的问题,这也不是)。++ve for sir,这是一个很好的解决方案,你能解释一下吗。“我会感谢你的。”拉文德辛格13,我已经添加了这样一个解释。祝你好运。如果要将此机制用于加密密钥等,则一定要谨慎。
var="abcdefghijklmnopqrstuvwxyz"
n=${#var}
idx=32769; while (( idx >= (32768/n)*n )); do idx=$RANDOM; done
char=${var:$idx:1}
/* A linear congruential random number generator based on the example
   one in the ANSI C standard. This one isn't very good, but a more
   complicated one is overkill.
*/