web-dev-qa-db-ja.com

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 that_script_above.sh 6によってzshで呼び出すと、次のような同じ文字の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

bashzshの両方で希望どおりに機能します。

だから、ここに私の質問があります:

  1. 上記のzshbashの動作に関する私の問題について誰かが私に説明できますか?
  2. そして、カスタマイズ可能な変数を使用してbashでforループを使用するにはどうすればよいですか? for i in {1..$1}はbashでは機能しないようです。
1
user312781

Q1。コマンド置換(バッククォート)はサブシェルを使用し、zshではサブシェルのRNG状態は再シードされません。親で_$RANDOM_を使用せずに新しいサブシェルを繰り返し作成するため、各サブシェルで同じ値を取得します。見る:
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

コマンド置換とエコーは必要ありません。また、配列の添え字はすでに算術式として評価されているため、$((..))も必要ありませんが、zsh配列は1であるため、+ 1が必要です。 -起源(あなたは幸運にも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}")

7