Search code examples
bashrandomgnu-coreutils

Shuffling numbers in bash using seed


I want to create an array of integers, where the numbers are from 1...N. Each number appears once in this array. For instance array = {1, 3, 5, 2, 4} when N = 5.

In order to produce this array, I use the shuffle method as:

        array=($(shuf -i 1-$N -n $N ))

It works fine. However, I want to add seed to this code to make sure every time I run the code with the same seed, I get the same array. Is it possible to do that using the shuffle method?


Solution

  • The GNU implementation of shuf has a --random-source argument. Passing this argument with the name of a file with known contents will result in a reliable set of output.

    See the Random sources documentation in the GNU coreutils manual, which contains the following sample implementation:

    get_seeded_random()
    {
      seed="$1"
      openssl enc -aes-256-ctr -pass pass:"$seed" -nosalt \
        </dev/zero 2>/dev/null
    }
    
    shuf -i1-100 --random-source=<(get_seeded_random 42)
    

    To load a result into a bash array in a manner that doesn't rely on string-splitting (and thus the current value of IFS), your implementation may instead look like:

    # with bash 4.0 or newer
    readarray -t array < <(shuf -i1-100 --random-source=<(get_seeded_random 42))
    
    # or, supporting bash 3.x as well
    IFS=$'\n' read -r -d '' -a array \
      < <(shuf -i1-100 --random-source=<(get_seeded_random 42) && printf '\0')