Bash: How do I truncate an array?

I'd like to change the value of an array and would appreciate any help.

I got an array like this:

users=(root isometric akau)

(This is actually a list of current users) that I'd like to be able to test if the user exists and if they do not, then to remove the person from the array. I've tried experiment with this by putting it in a for loop and evaluating it:

for i in ${users[@]}; do
  eval "users=($([ -z $(grep \"^\$i\" /etc/shadow) ] && sed \"s/\$i//g\"))"
done

echo $users

I thought about playing with this some more but I thought I might be getting too complicated (I'm not sure I can put a command in an array). Anyone have an idea on how to do this?

Edit:

How I entered the array variable unset number:

cnt=0
for i in ${users[@]}; do
  [ -z "$(grep "^$i" /etc/shadow)" ] && unset users[cnt] || ((cnt++))
done

Edit2:

Actually Dennis's is even better.

Upvotes: 2

Views: 3402

Answers (4)

Dennis Williamson
Dennis Williamson

Reputation: 360405

You may not need a for loop. Try this:

users=(root isometric akau)
list="${users[@]/%/|}"      # convert array to list, add pipe char after each user
# strip the spaces from the list and look for usernames between the beg. of the line
# and the end of the word, make an array out of the result
users=($(grep -Eo "^(${list// })\>" /etc/shadow))

The grep, unraveled, would look like this:

grep -Eo "^(root|isometric|akau|)\>" /etc/shadow

Upvotes: 5

ghostdog74
ghostdog74

Reputation: 342759

users=(root nobody akau)
declare -a shadowusers
declare -a notinshadow
i=0
while IFS=":" read -r user b c d e f g h
do
    shadowusers[$i]=$user
    i=$((i+1))
done < "/etc/shadow"
for u in ${users[@]}
do
    found=0
    for s in ${shadowusers[@]}
    do
           case "$u" in
               "$s") found=1;;
           esac   
    done
    [ "$found" -eq 0 ] && notinshadow[$j]=$u
    j=$((j+1)) 
done 
echo ${notinshadow[@]}

Upvotes: 0

DigitalRoss
DigitalRoss

Reputation: 146171

So if you have...

$ users=(root isometric akau)
$ echo ${users[*]}
root isometric akau

All you need to do is, say:

$ unset users[1]

And then...

$ echo ${users[*]}
root akau
$ 

Upvotes: 4

guns
guns

Reputation: 10815

If you want to remove jane from users:

users=(john joe mary jane liz root foobar)

for ((i = 0; i < ${#users[@]}; ++i)); do
    [[ ${users[i]} == jane ]] && break
done

users=(${users[@]:0:i} ${users[@]:i+1})

echo "${users[@]}" #=> john joe mary liz root foobar

The general principle is that there is no array slice in bash (obviously); you have to recreate the array without the excluded element(s).

That said, there are numerous ways to do what your are looking for in a for(in) loop.

Upvotes: 0

Related Questions