Як рандомізувати вихід із послідовностей?


11

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

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

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

Відповіді:


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

Але ти маєш якось форматувати, щоб їх перевести на одну лінію з комами. echo $(seq 10 | shuf)наближається, але не робить коми.
mikeserv

Перед ним горизонтально paste...
mikeserv

@mikeserv - змінив його навколо.
slm

Так. Ось так. Я pasteне знав , що це зробив. Дякую, що ви навчали мене. Майте нагороду.
mikeserv

@mikeserv - так прочитати сайт , дивлячись на будь-який шахті, Stephane - х або Жиль, використовуючи joinі paste. Ці два інструменти надзвичайно потужні.
slm

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

Шуби. Я бачив це теж у, 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,

А потім вони у вашому масиві оболонок.

Якщо ви отримаєте їх у масиві оболонок, вам навіть не потрібно 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

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()насіння генератора псевдовипадкових випадків на основі поточного часу).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.