我有这个脚本从定义的字符列表中生成 $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
。
所以,这是我的问题:
- 有人可以向我解释一下我上述 zsh bash 行为的问题吗?
- 如何在 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-subshells-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}")