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 '20 at 12:45
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 '20 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 '20 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 '20 at 15:54
  • @glennjackman very good points, thanks.
    – terdon
    May 5 '20 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

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .