【问题标题】:How to select a random item from an array in shell如何从shell中的数组中选择一个随机项
【发布时间】:2011-01-24 05:08:17
【问题描述】:

我正在使用 Shell 脚本创建一个机器人:

# Array with expressions
expressions=("Ploink Poink" "I Need Oil" "Some Bytes are Missing!" "Poink Poink" "Piiiip Beeeep!!" "Hello" "Whoops! I'm out of memmory!")

# Seed random generator
RANDOM=$$$(date +%s)

# Loop loop loop loop loop loop ...
while [ 1 ]
do
    # Get random expression...
    selectedexpression=${expressions[$RANDOM % ${#RANDOM[*]}]}

    # Write to Shell
    echo $selectedexpression


    # Wait an half hour
    sleep 1 # It's one second for debugging, dear SOers
done

我希望它每秒从expressions 中打印一个随机项目。我试过这个,但它不起作用。它每次只打印第一个(Ploink Poink)。谁能帮我吗? 谢谢

【问题讨论】:

  • 标签应该是固定的——POSIX shell中没有数组。

标签: arrays shell random


【解决方案1】:

将定义selectedexpression 的行更改为

selectedexpression=${expressions[$RANDOM % ${#expressions[@]} ]}

您希望 expression 的索引是从 0 到 expression 数组长度的随机数。这样就可以了。

【讨论】:

  • 请注意,该代码仍将偏向于较低的数组索引。
  • 是的。但是,除非您的表达式列表很长,否则效果很小。 $RANDOM 是一个介于 0 和 32767 之间的数字。假设您的列表中有 100 个项目。前 67 个项目的几率为 328/32767 (.01001),而后 33 个项目的几率为 327/32767 (.00998)。对于较短的列表,差异会更小。不过,您说得很好,shell RANDOM 函数不适用于必须具有真正随机数的情况,例如密码学。
  • 对于任何得到此答案并将其应用于 ZSH 的人:ZSH 中的数组索引从 1 开始(出于某种原因),因此将语句更改为:selectedexpression=${expressions[$(($RANDOM % ${#expressions[@]} + 1 ))]}
  • 谢谢@loklaan,你是我的救命恩人
  • 要获得均匀分布,您可以通过在 0.0 和 1.0 之间缩放随机浮点数来生成随机数。数组a 的示例:echo "${a[$(awk '{srand($2); print int(rand()*$1)}' <<< "${#a[@]} $RANDOM")]}"。或者使用像 shuf -n1 -i0-...jot -r 1 0 ... 这样的程序来为你完成这项工作。
【解决方案2】:
arr[0]="Ploink Poink"
arr[1]="I Need Oil"
arr[2]="Some Bytes are Missing!"
arr[3]="Poink Poink"
arr[4]="Piiiip Beeeep!!"
arr[5]="Hello"
arr[6]="Whoops! I'm out of memmory!"
rand=$[$RANDOM % ${#arr[@]}]
echo $(date)
echo ${arr[$rand]}

【讨论】:

  • 这给了 - Mon Mar 13 10:04:55 IST 2017 Whoops! I'm out of memmory!
  • 可以在数组中添加其他项目,例如arr[7]="Zip, ding, another line."
【解决方案3】:

这是另一种解决方案,它可能比 Jacob Mattison 的解决方案更随机(从 jot 手册页很难说):

declare -a expressions=('Ploink' 'I Need Oil' 'Some Bytes are Missing' 'Poink Poink' 'Piiiip Beeeep' 'Hello' 'Whoops I am out of memory')
index=$( jot -r 1  0 $((${#expressions[@]} - 1)) )
selected_expression=${expressions[index]}

【讨论】:

  • This jot implementation 使用浮点计算来生成随机数。系统的random() 函数缩小到0.01.0 之间的数字,然后放大到参数中给定的范围,因此我认为分布是均匀的。
【解决方案4】:

使用 shuf 的解决方案:

expressions=("Ploink Poink" "I Need Oil" "Some Bytes are Missing!" "Poink Poink" "Piiiip Beeeep!!" "Hello" "Whoops! I'm out of memmory!")
selectedexpression=$(printf "%s\n" "${expressions[@]}" | shuf -n1)
echo $selectedexpression

或者可能更好:

select_random() {
    printf "%s\0" "$@" | shuf -z -n1 | tr -d '\0'
}

expressions=("Ploink Poink" "I Need Oil" "Some Bytes are Missing!" "Poink Poink" "Piiiip Beeeep!!" "Hello" "Whoops! I'm out of memmory!")
selectedexpression=$(select_random "${expressions[@]}")
echo "$selectedexpression"

【讨论】:

    【解决方案5】:

    对于随机

    1.

    rand=("q" "w") 
    r=$(shuf -i 0-${#jndi[@]} -n 1)
    echo ${rand[$r]}
    
    1. echo $((1 + $RAND % 5)) // 用于 1..5 之间的数字

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-01
      • 2021-07-06
      • 2015-02-18
      • 2020-10-04
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      相关资源
      最近更新 更多