On Wed, Oct 21, 2026 at 20:30:25 +0200, Franco Martelli wrote:
> First of all thanks Greg for your patience explaining me coding. I'm
> interested about avoid to call an external tool inside the loop, do you have
> a snippet of code that provides random numbers in a specified range using a
> bash function?

https://mywiki.wooledge.org/BashFAQ/026

> You talked me about a Bash function able to return a random value between 1
> and n, at page #107 of the ABS I see that I have to use the 'modulo'
> operator to apply a range to a variable assigned with $RANDOM but it doesn't
> explain how to start from 1 and not from 0. Do I have to accept ranges from
> 0 to n and then discard the 0?

Well, usually you want 0 to n-1 because arrays are indexed from 0.  If
you want 1 to n, you can use something that gives you 0 to n-1, and
then add 1 to it.

Given an array of n elements, if we first store the size in a variable
for convenience:

    n=${#array[@]}

then the *easiest* way to select a random element (0 to n-1) is to use:

    ${array[RANDOM % n]}

But as FAQ 26 explains, this is imperfect.  There is a bias toward the
lower numbers (unless n is an exact divisor of 32768).  So, you have
to decide whether you can live with that bias or not.  For something
that's just generating a playlist of songs, this may be good enough.

Otherwise, you can use a function like this one from FAQ 26:

    rand() {
        local max=$((32768 / $1 * $1))
        while (( (r=RANDOM) >= max )); do :; done
        r=$(( r % $1 ))
    }

You'd use it like this:

    clips=(...)
    n=${#clips[@]}
    declare -A chosen
    playlist=()

    for i in {1..10}; do
        # Get an unused clip, which may take several tries.
        while true; do
            rand "$n"   # Get a clip index number in global variable r.
            [[ ${chosen[$r]} ]] && continue

            # If we get to this point, it's a new one.
            chosen[r]=1
            playlist+=( "${clips[r]}" )
            break
        done
    done

That generates a "playlist" array with 10 randomly selected, unique
elements from the "clips" array.  I didn't add any sanity checking,
so there are some obvious issues, like an infinite loop if clips
has fewer than 10 elements.  But it should be a decent starting point.

Another algorithm for solving this same problem would be to randomly
shuffle the clips array, and then use the first 10 elements as your
playlist.  I won't include code for that, but you should be able to
do that using the examples in FAQ 26.

Reply via email to