You are not logged in.
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
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
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
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
i think this methode with the counter is crap
when i remove one item from the array the counter doesn't match anymore
Offline
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
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
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
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
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
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
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
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.
"...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