从 bash 数组中提取 x 个随机值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6859249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extracting x random values from a bash array
提问by Rsaesha
I have an array in Bash, say it contains the numbers {1, 2, 3, 4, 5}. I want to extract some of those numbers randomly, such that the same number doesn't get extracted twice.
我在 Bash 中有一个数组,假设它包含数字 {1, 2, 3, 4, 5}。我想随机提取其中一些数字,这样相同的数字就不会被提取两次。
Basically, if I wanted to extract 3 numbers from the array, I want results like: {3, 4, 1} or {5, 2, 4} and not {1, 1, 3} or {2, 5, 2}.
基本上,如果我想从数组中提取 3 个数字,我想要的结果是:{3, 4, 1} 或 {5, 2, 4} 而不是 {1, 1, 3} 或 {2, 5, 2} .
I've tried deleting elements as I extract them, but it always seems to mess up. Can anyone help?
我试过在提取元素时删除它们,但它似乎总是一团糟。任何人都可以帮忙吗?
回答by Anders Lindahl
Decided to write an answer, as I found the --input-rangeoption to shufthat turned out handy:
决定写一个答案,因为我发现这个--input-range选项shuf很方便:
N=3
ARRAY=( zero one two three four five )
for index in $(shuf --input-range=0-$(( ${#ARRAY[*]} - 1 )) -n ${N})
do
echo ${ARRAY[$index]}
done
回答by Matt
How about this:
这个怎么样:
for i in {1..10}; do
echo $i
done | shuf
That will return all the numbers. If you only want a specific amount, do this:
这将返回所有数字。如果您只想要特定数量,请执行以下操作:
numbers=5
for i in {1..10}; do
echo $i
done | shuf | head -$numbers
And if you want to change the numbers, just change the {1..10}variable to whatever you want.
如果您想更改数字,只需将{1..10}变量更改为您想要的任何值。
回答by mivk
Yet another syntax, still using shuf, and preserving elements with spaces:
另一个语法,仍然使用shuf, 并用空格保留元素:
N=3
ARRAY=( one "two = 2" "3 is three" 4 five )
for el in "${ARRAY[@]}"; do echo $el; done | shuf | head -$N
回答by gniourf_gniourf
This might work for you, if you want a genuine pure bash solution.
如果您想要一个真正的纯 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= i
_takeNrandom_out=()
shift
while((k-->0 && $#)); do
((i=RANDOM%$#+1))
_takeNrandom_out+=( "${!i}" )
set -- "${@:1:i-1}" "${@:i+1}"
done
}
Try it:
尝试一下:
$ 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")'
(the newline is really preserved in the array field).
(换行符确实保留在数组字段中)。
This uses positional parameters, and uses set -- "${@:1:i-1}" "${@:i+1}"to remove the i-th positional parameter. We also used indirect expansion in the line _takeNrandom_out+=( "${!i}" )to have access to the i-th positional parameter.
这使用位置参数,并用于set -- "${@:1:i-1}" "${@:i+1}"删除第i-th 位置参数。我们还在行中使用了间接扩展_takeNrandom_out+=( "${!i}" )来访问i-th 位置参数。
Note.This uses the RANDOMvariable with a modulo, so the distribution is not exactly uniform. It should be fine for arrays with a small number of fields. Anyway if you have a huge array, you probably shouldn't be using Bash in the first place!
笔记。这使用RANDOM带模数的变量,因此分布并不完全均匀。对于具有少量字段的数组应该没问题。无论如何,如果你有一个庞大的数组,你可能一开始就不应该使用 Bash!
回答by RASG
very simple 'oneliner' i like:
非常简单的“oneliner”,我喜欢:
shuf -e ${POOL[@]} -n3
will give you 3 random elements from your $POOLarray
将从您的$POOL数组中为您提供 3 个随机元素
ex:
前任:
#~ POOL=(a b c d e)
#~ shuf -e ${POOL[@]} -n3
d
e
a

