我在Bash中有一个数组,说它包含数字{1,2,3,4,5}。我想随机提取其中一些数字,这样相同的数字就不会被提取两次。
基本上,如果我想从数组中提取3个数字,我想要的结果如:{3,4,1}或{5,2,4}而不是{1,1,3}或{2,5 ,2}。
我尝试删除元素,因为我提取它们,但它似乎总是搞砸了。有人可以帮忙吗?
答案 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