从bash数组中提取x个随机值

时间:2011-07-28 12:52:12

标签: arrays bash

我在Bash中有一个数组,说它包含数字{1,2,3,4,5}。我想随机提取其中一些数字,这样相同的数字就不会被提取两次。

基本上,如果我想从数组中提取3个数字,我想要的结果如:{3,4,1}或{5,2,4}而不是{1,1,3}或{2,5 ,2}。

我尝试删除元素,因为我提取它们,但它似乎总是搞砸了。有人可以帮忙吗?

5 个答案:

答案 0 :(得分:11)

决定写一个答案,因为我找到--input-range的{​​{1}}选项,结果很方便:

shuf

答案 1 :(得分:2)

这个怎么样:

for i in {1..10}; do
    echo $i
done | shuf 

这将返回所有数字。如果您只想要特定金额,请执行以下操作:

numbers=5    
for i in {1..10}; do
    echo $i
done | shuf | head -$numbers 

如果您想更改数字,只需将{1..10}变量更改为您想要的任何内容。

答案 2 :(得分:1)

另一种语法,仍然使用shuf,并使用空格保留元素:

N=3
ARRAY=( one "two = 2" "3 is three" 4 five )


for el in "${ARRAY[@]}"; do echo $el; done | shuf | head -$N

答案 3 :(得分:0)

如果你想要一个真正的纯粹的bash解决方案,这可能对你有用。

takeNrandom() {
# This function takes n+1 parameters: k a1 a2 ... an
# Where k in 0..n
# This function sets the global variable _takeNrandom_out as an array that
# consists of k elements chosen at random among a1 a2 ... an with no repetition
    local k=$1 i
    _takeNrandom_out=()
    shift
    while((k-->0 && $#)); do
        ((i=RANDOM%$#+1))
        _takeNrandom_out+=( "${!i}" )
        set -- "${@:1:i-1}" "${@:i+1}"
    done
}

试一试:

$ array=( $'a field with\na newline' 'a second field' 'and a third one' 42 )
$ takeNrandom 2 "${array[@]}"
$ declare -p _takeNrandom_out
declare -a _takeNrandom_out='([0]="a second field" [1]="a field with
a newline" [2]="and a third one")'

(换行确实保留在数组字段中。)

这使用位置参数,并使用set -- "${@:1:i-1}" "${@:i+1}"删除i位置参数。我们还在行_takeNrandom_out+=( "${!i}" )中使用了间接扩展来访问i位置参数。

注意。这会将RANDOM变量与模数一起使用,因此分布不完全一致。对于具有少量字段的数组应该没问题。无论如何,如果你有一个巨大的数组,你可能不应该首先使用Bash!

答案 4 :(得分:0)

我喜欢的非常简单的“单身”:

shuf -e ${POOL[@]} -n3

将从您的$POOL数组中随机选出3个元素

例如:

#~ POOL=(a b c d e)
#~ shuf -e ${POOL[@]} -n3

d
e
a