Как рандомизировать вывод из seq?

11

Я знаю, что могу использовать seqдля генерации случайного списка чисел: 1, 2, 3, 4 ...

Я хочу получить эти числа в случайном порядке, как 3, 1, 4, 2 ...

Я знаю, что могу использовать, shufчтобы перетасовать строки файла. Так что я мог бы использовать seqдля записи случайных чисел в файл, а затем использовать, shufчтобы перемешать их - или написать какую-то функцию перемешивания. Но это кажется излишне сложным. Есть ли более простой способ рандомизировать элементы в массиве с помощью одной команды?

bernie2436
источник

Ответы:

16

Вы можете просто передать вывод shuf.

$ seq 100 | shuf

пример

$ seq 10 | shuf
2
6
4
8
1
3
10
7
9
5

Если вы хотите , чтобы вывод горизонтальным затем через канал, paste.

$ seq 10 | shuf | paste - -s -d ' '
1 6 9 3 8 4 10 7 2 5 

$ seq 10 | shuf | paste - -s -d ' '
7 4 6 1 8 3 10 5 9 2 

$ seq 10 | shuf | paste - -s -d ' '
9 8 3 6 1 2 10 4 7 5 

Хотите это с запятыми между? Измените разделитель на paste:

$ seq 10 | shuf | paste - -s -d ','
2,4,9,1,8,7,3,5,10,6
SLM
источник
Но вам нужно как-то отформатировать, чтобы получить их в одну строку с запятыми. echo $(seq 10 | shuf)подходит близко, но не делает запятые.
mikeserv
До горизонтали paste...
mikeserv
@mikeserv - изменил это вокруг.
СЛМ
Да. Вот и ты. Я не знал, pasteсделал это. Спасибо, что научил меня. Имейте upvote.
mikeserv
@mikeserv - да, читайте на сайте, просматривая мои, Стефана или Жиля А, joinи paste. Эти 2 инструмента очень мощные.
СЛМ
3

Есть ли более простой способ рандомизировать элементы в массиве с помощью одной команды?

Предполагая, что у вас есть массив десятичных целых чисел:

arr=(4 8 14 18 24 29 32 37 42)

Вы можете использовать printfи shufдля рандомизации элементов массива:

$ arr=($(printf "%d\n" "${arr[@]}" | shuf))
$ echo "${arr[@]}"
4 37 32 14 24 8 29 42 18

(Выше предполагается, что вы не изменились $IFS).


Если все, что вам нужно, это случайные числа между двумя целыми числами, скажем, 10и 20, вам не нужны никакие дополнительные процессы, кроме как shufс помощью -iопции:

$ shuf -i 10-20
12
10
20
14
16
19
13
11
18
17
15

Цитирование из man shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line
devnull
источник
Чепуха. Я видел это тоже, shuf --helpно я пытался использовать shuf -i 1 10без вмешательства, -dash.ну, хорошо, хорошая работа - мой голос.
mikeserv
2
printf '%s, ' `seq 1 10 | shuf`

Вам даже не нужна forпетля.

ВЫХОД

7, 3, 4, 10, 2, 9, 1, 8, 5, 6,

Чтобы получить их в массиве оболочки, вы должны:

( set -- $(seq 1 10 | shuf) ; printf '%s, ' "$@" )

ВЫХОД

5, 9, 7, 2, 4, 3, 6, 1, 10, 8,

И тогда они в вашем массиве оболочки.

Если вы получаете их в массиве shell, вам даже не нужно printf:

( set -- $(seq 1 10 | shuf); IFS=, ; echo "$*" )

ВЫХОД

9,4,10,3,1,2,7,5,6,8

Кстати, seqи printfвроде как созданы друг для друга. Например, если я хочу повторить строку 1000 раз?

printf 'a string\n%.0b' `seq 1 1000`

ВЫХОД

a string

... 999 a stringстрок спустя ...

a string

Или...

printf 'a string,%.0b' `seq 1 10`

ВЫХОД

a string,a string,a string,a string,a string,a string,a string,a string,a string,a string,

Я хочу выполнить команду 39 раз?

printf 'echo "run %d"\n' `seq 1 39` | . /dev/stdin

ВЫХОД

run 1

... 38 runстрок спустя ...

run 39
mikeserv
источник
1

Вы можете использовать shufкоманду для рандомизации вывода, например

%> for x in $(seq 1 10 | shuf); do echo -n "$x "; done; echo
4 10 8 7 1 6 3 5 2 9 
маргаритка
источник
1

POSIXly, для генерации перемешанного списка десятичных целых чисел из minдо max:

awk -v min=1 -v max=10 'BEGIN{
  for (i = min; i <= max; i++) a[i] = i
  srand()
  for (i = min; i <= max; i++) {
    j = int(rand() * (max - min + 1)) + min
    tmp = a[i]; a[i] = a[j]; a[j] = tmp
  }
  for (i = min; i <= max; i++) print a[i]
}'

Помните, что во многих реализациях awk выполнение этой команды дважды в течение одной и той же секунды приведет к тому же результату (что и приводит srand()к генерации псевдослучайного генератора на основе текущего времени).

Стефан Шазелас
источник