Comportamento estranho no gerador aleatório zsh

1

Eu tenho este script para gerar $ 1 dígito (s) de caractere aleatório misto das listas de caracteres definidas como matrizes.

#!/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

Ele roda bem no bash, mas se eu invoco com zsh por zsh that_script_above.sh 6 ele apenas gera 6 dígitos de algum mesmo caractere como este:

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

E se eu modifiquei esse script para ser assim:

#!/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

funciona bem como eu desejei para bash e zsh .

Então, aqui estão minhas perguntas:

  1. Alguém pode me explicar sobre o meu problema com o comportamento de zsh bash mencionado acima?
  2. E como posso usar para loop no bash com variável personalizável? porque parece que for i in {1..$1} não funciona no bash.
por user312781 26.09.2018 / 03:57

1 resposta

6

Q1. A substituição de comandos (backticks) usa um subshell e, em zsh, o estado RNG de um subshell não é propagado novamente. Como você cria repetidamente um novo subshell sem usar $RANDOM no pai, você obtém o mesmo valor em cada subshell. Veja:
link - < href="https://superuser.com/questions/1210435/different-behavior-of-in-zsh-and-bash-functions"> link

Você não precisa do comando-substitution e echo, e você também não precisa do $((..)) porque um subscrito do array já é avaliado como uma expressão aritmética, mas você precisa do +1 porque o zsh arrays é 1- origem (você teve sorte de não ter acertado 0):

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

Além de: mesmo se você precisou de uma substituição de comando echo em você não precisa de -n porque a própria substituição de comando remove qualquer nova linha (s) à direita dos dados capturados e substituídos.

Q2. O bash faz a expansão de chaves antes de fazer a expansão de parâmetros (e substituições e expansões de comandos e aritméticas), mas zsh (e ksh) faz isso depois. Você pode usar for i in $(seq 1 $1) ou yucky mas incorporado em for i in $(eval "echo {1..$n}")

    
por 26.09.2018 / 09:01