zsh 随机生成器中的奇怪行为

zsh 随机生成器中的奇怪行为

我有这个脚本从定义的字符列表中生成 $1 数字的混合随机字符作为数组。

#!/bin/bash

charlist1=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
charlist2=(0 1 2 3 4 5 6 7 8 9)
charlists=(${charlist1[*]} ${charlist2[*]})

i="1"
while [ $i -le $1 ]; do
    out=$out`echo -n ${charlists[$(($RANDOM % ${#charlists[*]}))]}`
    i=$(( i + 1 ))
done

echo $out

它在 bash 中运行良好,但是如果我用 zsh 调用它,zsh that_script_above.sh 6它只会生成一些相同字符的 6 位数字,如下所示:

>>> zsh that_script_above.sh 6
llllll
>>> zsh that_script_above.sh 6
bbbbbb

如果我将该脚本修改为如下所示:

#!/bin/bash

charlist1=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
charlist2=(0 1 2 3 4 5 6 7 8 9)
charlists=(${charlist1[*]} ${charlist2[*]})

i="1"
while [ $i -le $1 ]; do

    echo -n ${charlists[$(($RANDOM % ${#charlists[*]}))]}

    i=$(( i + 1 ))
done

echo

它的效果很好,正如我对bash和 的期望zsh

所以,这是我的问题:

  1. 有人可以向我解释一下我上述 zsh bash 行为的问题吗?
  2. 如何在 bash 中使用带有可自定义变量的 for 循环?因为它似乎for i in {1..$1}在 bash 中不起作用。

答案1

Q1.命令替换(反引号)使用子 shell,并且在 zsh 中,子 shell 的 RNG 状态不会重新播种。由于您重复创建新的子 shell 而不$RANDOM在父 shell 中使用,因此您在每个子 shell 中获得相同的值。看:
https://stackoverflow.com/questions/32577117/references-to-random-in-subshel​​ls-all-returning-identical-values
https://superuser.com/questions/1210435/ Different-behavior-of-in-zsh-and-bash-functions

您不需要命令替换和 echo,也不需要$((..))因为数组下标已经被计算为算术表达式,但您确实需要 +1,因为 zsh 数组是 1-origin (你很幸运没有碰巧达到 0):

 out=$out${charlists[ $RANDOM % ${#charlists[*]} + 1 ]}

另外:即使您确实需要echo命令内替换,您也不需要,-n因为命令替换本身会从捕获和替换的数据中删除任何尾随换行符。

Q2。 bash 在进行参数扩展(以及命令和算术替换/扩展)之前进行大括号扩展,但 zsh(和 ksh)在之后进行。你可以使用for i in $(seq 1 $1)或 yucky 但内置的for i in $(eval "echo {1..$n}")

相关内容