# Finishing Up the Content Spinner

### Pick a Card, Any Card

The basic way to work with random numbers in Bash is to use the special `\$RANDOM` variable. Each time it's referenced, it returns a randomly chosen number between 1 and MAXINT (32767). I constrain it to a specific range by using the modulus function, so this will generate a random number between 0 and MAXVALUE:

``````
randomnum=\$(( \$RANDOM % \$MAXVALUE ))
```
```

The double-parent notation triggers mathematical evaluation, but you already know that, right?

To make the bottom be the value 1 instead of zero, I just add a bit more math to the equation:

``````
randomnum=\$(( \$RANDOM % \$MAXVALUE + 1 ))
```
```

The script already can identify how many choices are in a specific cluster (for example, "{one|two|three}"), and now we have a simple one-liner to help randomly pick one of the values. The challenge, of course, is to pick the actual string value, not just show a number!

I know, I know—work, work, work.

Halfway through the `spinline()` function (which I'll show in its entirety in just a sec), `\$choices` stores the count of how many options are in the cluster, and `\$source` is the set of choices, minus the open and close curly brackets.

Here's my first attempt at the random word extraction:

``````
pick=\$(( \$RANDOM % \$choices ))
wordpick=\$( echo \$source | cut -d\| -f\$pick )
```
```

But, that generates an error message when run. It's not because of a typo, however—it's legit to use `cut` and specify the pipe symbol as the field delimiter—but because I haven't compensated for the 0..n selection of the random number generator: request field `-f0` from `cut`, and it complains because, well, there is no field zero.

That's easily fixed now that I understand the problem, however, and so here's version two:

``````
pick=\$(( \$RANDOM % \$choices + 1 ))
wordpick=\$( echo \$source | cut -d\| -f\$pick )
```
```

Remember that modulus returns 0..(n-1) for its values, so when there are three choices, for example, `\$RANDOM % 3` returns 0, 1 or 2. Add one to each, and it's back on track with the values 1, 2 and 3.

With a few useful debugging lines, here's the function in its entirety:

``````
function spinline()
{
source="\$*"
choices=\$(grep -o '|' <<< "\$*" | wc -l)
choices=\$(( \$choices + 1 ))
echo \$choices options, spinning --- \$source
pick=\$(( \$RANDOM % \$choices + 1 ))
wordpick=\$( echo \$source | cut -d\| -f\$pick )
echo I pick choice \$pick which is \$wordpick
}
```
```

Yeah, code. Let's see what happens when I run it with the test sentence as input:

``````
\$ sh spinner.sh spinme.txt
The
3 options, spinning --- idea|concept|inspiration
I pick choice 2 which is concept
is that each time you'd use a
2 options, spinning --- word|phrase
I pick choice 1 which is word
you instead list a set of
3 options, spinning --- similar words|synonyms|alternative words
I pick choice 2 which is synonyms
and the software automatically picks one
2 options, spinning --- randomly|at random
I pick choice 2 which is at random
and is done.
```
```

It's close, actually—really close!

______________________

Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.