定義された文字リストの配列として $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.コマンド置換(バックティック)はサブシェルを使用し、zshではサブシェルのRNGステータスは再シードされません。親シェルで使用せずに新しいサブシェルを繰り返し作成するため、$RANDOM
各サブシェルで同じ値を取得します。望むより:
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
コマンド置換とエコーは不要で、$((..))
配列添え字はすでに算術式で評価されているため必要ありませんが、zsh配列は1原点であるため+1が必要です(0に達していないことは幸運です)。
out=$out${charlists[ $RANDOM % ${#charlists[*]} + 1 ]}
また、コマンド内の置換が必要な場合でもecho
そうではありません。-n
これは、コマンド置換自体がキャプチャされ、置き換えられたデータから末尾の改行を削除するためです。
Q2. bashは引数拡張(およびコマンドと算術置換/拡張)の前に中括弧拡張を実行しますが、zsh(およびksh)はその後実行します。 yuckyまたはyuckyを使用できますが、for i in $(seq 1 $1)
組み込みfor i in $(eval "echo {1..$n}")