0

I'm trying to get a random character print out in an array that is stored with characters. I'm new to bash and been looking at some guides along the way but have run into a bit of a problem.

I create an array to test with which stores chars. I then have a variable called Range which is 21 (this is the length of the array).

 #create an characters to test with
 letters=(a,b,e,g,i,j,k,l,m,n,p,q,r,s,t,u,v,y,x,w,z)

 RANGE=21

I then try and get a random number from 0 -> range, so it will correspond with array indices. I then need to access the array index of the random number and store that in a variable called arraychar. I have done it like this:

number=$RANDOM%$RANGE #gets int of a random number between 0 and range (size of array)
arraychar=${letters[$number]} #chooses a random char from array and stores in arraychar

Then I want to pass this letter as an argument to my executable like so:

for i in `seq 1 3`;do
   echo $i " "
   ./sample-tree -$arraychar
done

It keeps hanging here, and I'm not too sure what's it doing, and why it isn't working.

Any help would be appreciated as I'm a newbie!

Thanks.

2
  • 1
    That's not the syntax for creating an array in bash. You should have spaces, not commas, between the elements. Commented Sep 5, 2014 at 2:06
  • letters=({a..z}) syntax also works (at least on bash 4..) Commented Sep 5, 2014 at 7:56

1 Answer 1

2

There are a number of things wrong with the code snippets in your post.

letters=(a,b,e,g,i,j,k,l,m,n,p,q,r,s,t,u,v,y,x,w,z) is an array of one element. See what declare -p letters spits out at you to confirm. sh arrays are whitespace separated lists.

The length of an array in the shell is available via ${#letters[@]}.

number=$RANDOM%$RANGE is not doing what you expect it is. Again see what declare -p number says the value of the variable is (echo "$number" would work too).

You need arithmetic expansion to evaluate the modulus operation (i.e. number=$((RANDOM % RANGE))).

A couple other "stylistic" points as well:

  • You don't need $ in the array indexing context (e.g. ${letters[$number]} can be written as ${letters[number]}).
  • In bash (and many other shells) you can use {1..3} to get that list of numbers without needing a sub-shell and seq.
  • The trailing space in echo $i " " isn't going to do much for you because echo outputs a newline as well (unless you use -n but in that case you might just be better off with printf).
Sign up to request clarification or add additional context in comments.

4 Comments

declare -a letters='([0]="a,b,e,g,i,j,k,l,m,n,p,q,r,s,t,u,v,y,x,w,z")' Thanks, I'll try this again.
@user3530774 Right, notice the [0] there? That's the index. See how there is only one? Compare that to l=(a b c d); declare -p l.
@EtanReisner +1. Probably not hugely important here, but worth nothing that you shouldn't use $RANDOM for anything important, especially since depending on RANGE it may not even be expected to produce an even distribution of random numbers (since $RANDOM will be a pseudo random number between 0...32767)
Per @BroSlow on distribution, and bearing @EtanReiser's comments in mind. Assuming you get letters declared as an array, you need something like: CHOICE=$(echo "scale=6; $RANDOM/32767 * ${#letters}" | bc); CHOICE=${CHOICE/.*}; CHOICE=${CHOICE:-0}. Obviously this begs to be defined as a function with $1 replacing ${#letters}.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.