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.コマンド置換(バックティック)はサブシェルを使用し、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)はその後実行します。 yuckyまたはyuckyを使用できますが、for i in $(seq 1 $1)組み込みfor i in $(eval "echo {1..$n}")

関連情報