Your syntax is rather clunky, I'm afraid.  Refactoring to avoid dozens of superfluous external processes should also make the script more readable and maintainable, although you need to understand the new constructs.

Instead of doing a for loop over the output of cat, the usual idiom to read a file line by line is to use while read ...; do ...; done &lt;file and this also buys you the significant simplification that read will split the input into tokens for you.

Instead of calling $RANDOM three times, it would seem a lot more straightforward to call it once with a modulo of 1000 and add leading zeros if necessary.

And no, your arrays were not working right, but you don't even really need arrays here -- just do the stuff you want to do inside the main loop for each user.

As ever, you should properly quote every string unless you specifically require the shell to perform wildcard expansion and token splitting on the value.

I also took the liberty to fix the grep; if [ $? = 1 ]; then...  to just if ! grep; then... which is both simpler and more idiomatic, as well as more readable.  But then we should not use grep for examining passwords, so I replaced that with getent instead.  The construct getent || groupadd is basically shorthand for if ! getent; then groupadd; fi.

You were redirecting standard error from useradd to /dev/null but I took that away -- if there is a failure, you need to see the error message; otherwise you could spend hours debugging an error which would be obvious if you knew what's wrong.  (We see that here on StackOverflow a lot more than we should.)

One last note -- Bash has a simple built-in syntax for substring extraction; ${string:0:3} extracts a substring of length 3 at offset 0.  Similarly, ${string//foo/bar} returns the value of string with all occurrences of foo replaced with bar.

#!/bin/bash
while read last first middle groups; do
    rsy=$(prinf '%03i' $(($RANDOM % 1000)))
    username="${first:0:1}${last:0:3}$middle$rsy"
    echo "$username"
    for group in $groups; do
      getent group "$group" &gt;/dev/null || groupadd "$group"
    done
    password=$(LC_ALL=C tr -dc '!-~' &lt;/dev/urandom | head -c 14)
    enc=$(openssl passwd -1 "$password")
    useradd -n -G "${groups// /,}" -m "$username" -p "$enc" -d "/home/${groups%% *}/$username" #2&gt; /dev/null
    # Print generated user's first, last, UID, and password
    echo "$first $last $(id -u "$username") $password"
done &lt;"$1"


I have not attempted to enhance the useradd command -- as noted in the answer by @asimovwasright you probably need to do additional things to perform this properly.  If you are on a Debian-based distro, you should look into adduser as a higher-level replacement which takes care of many of these chores for you.

The password creation is a bit of a crock.  I adapted one of the answers from How to automatically add user account AND password with a Bash script? but it's probably not optimal from either a usability or a security standpoint.  But then, you should really not create passwords anyway -- just create users without passwords, put their SSH public key in place, and let them log in that way.

(I used /dev/random at first but it was taking forever in my tests so I switched to /dev/urandom.  I'm hoping you are making your users change their password first thing when they log in, so this should be an acceptable compromise.)

Bash script- Create usernames and passwords from txt file and store in group?
I'm stuck on continuing the next exercise:


  Considering:
  
  $\log_{c}a = 3$
  $\log_{c}b = 4$
  
  and:
  
  $$
y = \frac{a^{3}\sqrt{b \cdot c^{2}}}{2}
$$
  
  What's the value of $\log_{c}y$ (integer)?


So far, I did all the substitutions that were obvious at my eyes:

$$
y = \frac{a^{3}\sqrt{b \cdot c^{2}}}{2}\quad\rightarrow\quad
y = \frac{c^{9}\sqrt{c^{4} \cdot c^{2}}}{2}\quad\rightarrow\quad
y = \frac{c^{9}\sqrt{c^{6}}}{2}\quad\rightarrow\quad
y = \frac{c^{9} c^{3}}{2}\quad\rightarrow\quad
y = \frac{c^{12}}{2}
$$

The last equality is the same as $c^{12} = 2y$, which could be written as:

$$
\log_{c}2y = 12\quad\rightarrow\quad
\log_{c}2 + \log_{c}y = 12
$$

I really don't know haw to continue. I've managed to find a $\log_{c}y$, but I don't know what to do with the $\log_{c}2$. Either I took the wrong path, or I'm missing something that prevents me to finish this exercise.

Any hints are much welcome! Thanks in advance.
