我有一个例子,我试图在一组字母中随机生成一个字母(即var =“abcdefghijklmnopqrstuvwxyz”)。
我将如何:
var="abcdefghijklmnopqrstuvwxyz"
echo "${var}"
收益: some_letter
关键是,我正在尝试从我选择的选择中自动生成随机字母 。无论是数组还是字符串都没关系。
答案 0 :(得分:9)
var="abcdefghijklmnopqrstuvwxyz"
echo "${var:$(( RANDOM % ${#var} )):1}" # pick a 1 char substring starting at a random position
这是因为:
${var:START:LEN}
是parameter expansion,可扩展为$var
${#var}
是一个参数扩展,扩展为字符串变量var $(( ))
创建一个算术上下文,其中假定非数字字符串引用变量名称(因此可以使用RANDOM
代替$RANDOM
)。$RANDOM
,每次评估时,都会扩展为0到32767之间的随机整数。$RANDOM % ${#var}
将该随机整数的余数除以名为var
的字符串中的字符数;因此,它将在0和(var
- 1的长度)之间,并且几乎随机分割(如果 - var
的长度不是&#39 ; t均匀分为32768,然后某些字符被选中的几率略高于其他字符。)因此,${var:$(( RANDOM % ${#var} )) : 1}
每次评估时,都会在字符串中选择一个位置,并扩展到其中的单字符范围。
答案 1 :(得分:1)
对于大多数实际案例,Charles Duffy的解决方案是前进的方向。但是,如果您的随机字符选择必须是统一的,那么当您想要使用RANDOM
时,故事会变得稍微复杂一些(请参阅下面的说明)。最好的方法是使用shuf
。 shuf
生成给定范围的随机排列,并允许您选择第一个数字,如shuf -i 0-25 -n1
,以便您可以使用
var="abcdefghijklmnopqrstuvwxyz"
echo ${var:$(shuf -i 0-$((${#var}-1)) -n1):1}
随机变量RANDOM
生成0到32767之间的伪随机数。这意味着如果要生成0
和n
之间的随机数,则无法使用国防部。这里的问题是第一个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
另一种经典方法是将随机数生成器的范围映射到请求范围n*RANDOM/32768
。但是,这仅适用于生成实数的随机数生成器。 RANDOM
生成一个整数,因此您只需改变问题:
% for i in {0..32767}; do echo $((5*i/32768)); done | sort -g | uniq -c
6554 0
6554 1
6553 2 < smaller chance to hit 2
6554 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
背后的随机数生成器有多好。我们所做的只是引用来源中的评论:
来源bash 4.4.18(
variables.c
)/* 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. */
答案 2 :(得分:1)
您也可以使用一种更简洁的方式使用shuf
。
基本上,您将字符串分成两行,然后按常规方式使用shuf
:
使用fold
进行拆分
echo "abcdefghijklmnopqrstuvwxyz" | fold -w1 | shuf -n1
使用grep
进行拆分
echo "abcdefghijklmnopqrstuvwxyz" | grep -o . | shuf -n1