You are not logged in.

#1 2012-09-06 09:59:27

rootbox
Member
Registered: 2012-09-06
Posts: 10

How to remove an item from array in bash?

Hi

i tried serveral methods to remove an specific item from an array:

for host in ${HOSTNAMES[@]}
    do
        if [ "${host}" != $HOSTNAME ] ; then
            ping $host 1 &> /dev/null
            if test "$?" -eq "0" ; then
                echo "ok"
            else
                #here i want to remove $host from the array HOSTNAMES
            fi
        fi
    done

anyone have an idea, how i can remove the host?

Edit: The Device i want to run this script is an Unix System (Sun)

Last edited by rootbox (2012-09-06 10:01:41)

Offline

#2 2012-09-06 10:11:35

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: How to remove an item from array in bash?

I rarely use bash arrays - so consider this as one option that will likely be superseeded by better recommendations.  I'd copy the array into a new temporary array which could then be moved back to the HOSTNAMES array after the loop.  In other words, instead of trying to conditionally excise elements, conditionally append the items that pass the test to a new array.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#3 2012-09-06 10:17:30

skanky
Member
From: WAIS
Registered: 2009-10-23
Posts: 1,847

Re: How to remove an item from array in bash?

You'll need the index to clear:

unset HOSTNAMES[index]

Edit, incidentally you can skip empty items in the array by calling:

for host in {!HOSTNMES[@]}...etc...

Last edited by skanky (2012-09-06 10:19:05)


"...one cannot be angry when one looks at a penguin."  - John Ruskin
"Life in general is a bit shit, and so too is the internet. And that's all there is." - scepticisle

Offline

#4 2012-09-06 10:47:14

rootbox
Member
Registered: 2012-09-06
Posts: 10

Re: How to remove an item from array in bash?

So i tried:

i=0
ii=0
for host in ${HOSTNAMES[@]}
    do
      let i=i+1
      let ii=i-1 
      echo $ii
        if [ "${host}" != $HOSTNAME ] ; then
            ping $host 1 &> /dev/null
            if test "$?" -eq "0" ; then
                echo "ok"
            else
                unset HOSTNAMES[$i]
                echo ${HOSTNAMES[@]}
            fi
        fi
    done

but for any reasons it says:
./script: line 103: unset: HOSTNAMES: not an array variable

Offline

#5 2012-09-06 11:00:31

rootbox
Member
Registered: 2012-09-06
Posts: 10

Re: How to remove an item from array in bash?

i think this methode with the counter is crap hmm

when i remove one item from the array the counter doesn't match anymore sad

Offline

#6 2012-09-06 11:49:44

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,330
Website

Re: How to remove an item from array in bash?

When you remove one from the array, you should decrement the counter.  I have no idea why you have two counters.  Alternately, only increment the counter in the conditional code for when you dont remove and item.

So "if condition then incremement counter, else remove item at current position"

Last edited by Trilby (2012-09-06 11:51:32)


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Offline

#7 2012-09-06 12:49:44

skanky
Member
From: WAIS
Registered: 2009-10-23
Posts: 1,847

Re: How to remove an item from array in bash?

Do you populate the array? If so you could make it an associative array, and reference it thus:

HOSTNAMES[host]=host

That way you can remove it thus:

unset HOSTNAMES[$host]

Bit of a hack, but should work.

Otherwise you could just set it to an empty string and ignore empty strings in your processing. Not ideal.

Otherwise there are tricks with indexes and array sizes that are indicated in the Bash manual. I'd recommend reading the Arrays section of it.


"...one cannot be angry when one looks at a penguin."  - John Ruskin
"Life in general is a bit shit, and so too is the internet. And that's all there is." - scepticisle

Offline

#8 2012-09-06 13:10:22

rootbox
Member
Registered: 2012-09-06
Posts: 10

Re: How to remove an item from array in bash?

Trilby wrote:

When you remove one from the array, you should decrement the counter.  I have no idea why you have two counters.  Alternately, only increment the counter in the conditional code for when you dont remove and item.

So "if condition then incremement counter, else remove item at current position"

That works smile

I have to counter because $i counts one up so it starts with 1 but the array start with 0 so -1 in $ii

Offline

#9 2012-09-06 19:10:36

rockin turtle
Member
From: Montana, USA
Registered: 2009-10-22
Posts: 227

Re: How to remove an item from array in bash?

A problem with unset is that it will remove an item, but will not re-index the array.

#!/bin/bash

# create an array
xyz=(a b c d e)
echo ${xyz[@]}
orig_length=${#xyz[@]}

# remove an item
unset xyz[2]

echo ${xyz[@]}
echo

for (( i=0; i < orig_length; i++ )); do
	echo "$i: ${xyz[i]}"
done

If you are using bash as your shell, you can do the following to remove the desired host from an array. (This may not work in other shells.)

#!/bin/bash

HOSTNAMES=(a b c d e f c)
HOSTNAME=c

echo "${HOSTNAMES[@]}"
HOSTNAMES=($(for h in ${HOSTNAMES[@]}; do [ "$h" != "$HOSTNAME" ] && echo $h; done ))
echo "${HOSTNAMES[@]}"

#for host in "${HOSTNAMES[@]}"; do
#	ping "$host" 1 &> /dev/null && echo "${host}... ok"
#done

Offline

#10 2012-09-06 19:35:08

skanky
Member
From: WAIS
Registered: 2009-10-23
Posts: 1,847

Re: How to remove an item from array in bash?

rockin turtle wrote:

A problem with unset is that it will remove an item, but will not re-index the array.

That doesn't necessarily matter if you reference using

${!xyz[@]}

which will ignore any unset items.


That's just for future reference though.


"...one cannot be angry when one looks at a penguin."  - John Ruskin
"Life in general is a bit shit, and so too is the internet. And that's all there is." - scepticisle

Offline

#11 2012-09-06 21:08:51

rockin turtle
Member
From: Montana, USA
Registered: 2009-10-22
Posts: 227

Re: How to remove an item from array in bash?

skanky is correct, this is probably your best approach

for i in "${!HOSTNAMES[@]}"; do
	host="${HOSTNAMES[i]}"
	if [ "$host" != "$HOSTNAME" ]
		ping "$host" 1 &> /dev/null && echo "${host}... ok"
	else
		unset HOSTNAMES[i]
	fi
done

Edit: Oops, I see I got the logic from rootbox's original script incorrect.

Perhaps this will work.

for i in ${!HOSTNAMES[@]}; do
	host="${HOSTNAMES[i]}"
	[ "$host" == "$HOSTNAME" ] && continue
	ping $host 1 &> /dev/null || unset HOSTNAME[i]
done

Last edited by rockin turtle (2012-09-06 21:38:52)

Offline

#12 2012-09-06 21:16:23

skanky
Member
From: WAIS
Registered: 2009-10-23
Posts: 1,847

Re: How to remove an item from array in bash?

Yes sorry, I had forgotten that it expanded the array *keys* which makes it much more useful, and had posted/implied it returned the values.
It was checking rockin turtle's #11 solution that reminded me of the error.
My mistake and well caught. smile


"...one cannot be angry when one looks at a penguin."  - John Ruskin
"Life in general is a bit shit, and so too is the internet. And that's all there is." - scepticisle

Offline

Board footer

Powered by FluxBB