How to randomize the output from seq?

I know I can use seq to generate a random list of numbers: 1, 2, 3, 4…

I want to get those numbers into a random order like 3, 1, 4, 2…

I know I can use shuf to shuffle the lines of a file. So I could use seq to write random numbers to a file and then use shuf to shuffle them — or write some sort of shuffle function. But this seems needlessly complex. Is there a simpler way to randomize the items in an array with a single command?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can just pipe the output to shuf.

$ seq 100 | shuf

Example

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

If you want the output to be horizontal then pipe it to 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

Want it with commas in between? Change the delimiter to paste:

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

Method 2

Is there a simpler way to randomize the items in an array with a
single command?

Assuming you have an array of decimal integers:

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

You could use printf and shuf to randomize the elements of the array:

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

(the above assumes you’ve not modified $IFS).


If all that you need is random numbers between two integers, say 10 and 20, you do not need any extra processes other than shuf by using the -i option:

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

Quoting from man shuf:

   -i, --input-range=LO-HI
          treat each number LO through HI as an input line

Method 3

printf '%s, ' `seq 1 10 | shuf`

You don’t even need a for loop.

OUTPUT

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

To get them in a shell array you do:

( set -- $(seq 1 10 | shuf) ; printf '%s, ' "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d2f692">[email protected]</a>" )

OUTPUT

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

And then they’re in your shell array.

If you get them in the shell array, you don’t even need printf:

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

OUTPUT

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

By the way, seq and printf are kinda made for each other. For instance if I want to repeat a string 1000 times?

printf 'a stringn%.0b' `seq 1 1000`

OUTPUT

a string

… 999 a string lines later…

a string

Or…

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

OUTPUT

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

I want to execute a command 39 times?

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

OUTPUT

run 1

… 38 run lines later …

run 39

Method 4

You may use shuf command to randomize output, e.g

%> for x in $(seq 1 10 | shuf); do echo -n "$x "; done; echo
4 10 8 7 1 6 3 5 2 9

Method 5

POSIXly, to generate a shuffled list of the decimal integers from min to 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]
}'

Beware that with many awk implementations, running that command twice within the same second will produce the same result (as srand() seeds the pseudo-random generator based on the current time).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x