6

I'm trying to create a matrix of random numbers after prompting the user for the number of rows and columns of random numbers. I can only use nested for loops.

I have created two variables: rows and columns but my main problem is getting the for loop to echo properly. Here's my loop function

    for i in [1..$rows]; do
    echo "$RANDOM";
    done

I have tried to increment the value of i with 1+1 but not matter what it only runs the loop once. I want the script to read the value of $rows.

1
  • How will you use the random numbers? If you want to use them where it is critical that they are good random numbers and not predictable from a simple pseudo-random generator, you should not use RANDOM but /dev/urandom. See man urandom. (Examples of critical usage: to generate passwords or encryption keys.)
    – sudodus
    May 4, 2020 at 12:45

3 Answers 3

9

There is no syntax like [x..y]. You're probably thinking of {x..y}, but that doesn't work if either x or y are variables.

So, you could try one of these instead:

for((i=1;i<=$rows;i++)); do
    echo "$RANDOM"
done

Or

for i in $(seq 1 "$rows"); do
    echo "$RANDOM"
done

Or

i=0 
while (( ++i <= rows)); do
    echo "$RANDOM"; 
done

Or even

i=0
until [ $i -gt $rows ]; do 
    echo "$RANDOM"
    ((i++))
done
4
  • Perhaps use the arithmetic conditional while (( ++i <= rows)) May 5, 2020 at 12:30
  • @glennjackman done, thanks. Is there any benefit to that apart from being slightly shorter than my while [ $((i++)) -le $rows ]? It does feel more elegant, but is there some other consideration as well?
    – terdon
    May 5, 2020 at 12:52
  • 1
    Aside from the nicer syntax (less punctuation implies fewer errors), this protects you from some values of $rows: if rows is unset or empty, it gets value zero in arithmetic (with no $) -- unset or empty variable unquoted in brackets gives a syntax error (All variables in [...] should be quoted to protect from word splitting, filename expansion). May 5, 2020 at 15:54
  • @glennjackman very good points, thanks.
    – terdon
    May 5, 2020 at 16:57
5

As terdon pointed out, the syntax you use is not correct, and he went on to give a few examples of loops that would work.

However, to print $rows number of random integers, you may also use

jot -r "$rows"

or, equivalently,

jot -r "$rows" 1 100

which will output $rows random integers between 1 and 100 inclusively (jot is available on BSD systems, or in the athena-jot package on some Linux systems).

Or,

shuf -i 1-100 -r -n "$rows"

which will do the same as the jot command above (shuf is part of GNU coreutils).

To create a matrix of $cols times $rows entries, you could use rs (rs is available on BSD systems, or in the rs package on some Linux systems):

$ rows=4
$ cols=6
$ jot -r "$(( rows * cols ))" | rs "$rows" "$cols"
37  29  2   74  5   14
82  86  74  63  73  9
58  10  14  96  12  90
98  13  55  56  40  52

Note that we need $rows * $cols random numbers. The example used here gets these from jot, but shuf could also be used (or any other command that produces the numbers).

0

With zsh:

$ eval print -C4 '$(('{1..20}', RANDOM))'
11190  17138  16156  5735
16751  13545  22647  13244
12925  11584  10984  32387
32093  8170   5305   6102
25136  30299  3944   9956

Or using GNU shuf to specify the range:

$ print -C4 $(shuf -i 0-99 -n 20)
96  55  93  33
25  7   19  60
34  51  88  46
79  13  70  98
63  37  69  41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.