passing arrays and working with arrays in BASH
Charles Bennett
ccb-HInyCGIudOg at public.gmane.org
Fri Apr 2 08:34:31 EDT 2010
On Fri, 2010-03-26 at 17:12 -0400, theBlueSage wrote:
> Ho Folks,
>
> so it has taken me _ages_ to get this to work and Icant believe this is
> the best/only way to get this done :
>
> Problem :
> I am writing server install scripts, and BASH is the chosen tool. I
> needed to write a function that could receive an array and a value, and
> then simply return the position in the array if the given value. This is
> seriously easy in something like PHP using in_array($arr, $val), but in
> was a completely different kettle of fish in BASH.
>
> Solution (that I have working right now, in example form):
>
> ------------ start code snippet --------------
>
> #!/bin/bash
> function search_array() {
> index=0
> array=( "$@" )
> #echo ${array[@]}
> let TCNT=${#array[@]}-1
> LASTVAL=${array[${#array[@]}-1]}
> while [ "$index" -lt "$TCNT" ]; do
> if [ "${array[$index]}" = "$LASTVAL" ]; then
> echo $index
> return
> fi
> let "index++"
> done
> echo ""
> }
>
>
> echo -e -n "enter a value to search for : "
> read -e KEY
> arr=( f q e c d s a )
> arr[${#arr[@]}+1]=$KEY
> position=$(search_array "${arr[@]}")
> if [ -z "$position" ]; then
> echo -e "the value "$KEY" is not in the array"
> else
> echo -e "the value "$KEY" was found at position: "$position
> fi
> exit 0
>
>
> -------- end code snippet ----------------
>
> where : 'KEY' is the value to search for and 'arr' is the array to
> search in
>
>
> I did it this way as I couldn't find any other way to pass an array
> _and_ a scalar value to the function. The result is I add the scalar to
> the end of the array, pass it to the function and then peel it off
> again.
>
> SURELY there is a better way of doing it than this ?
>
> thanks for any suggestions
>
>
> Richard
>
Sorry to chime in so late.
Arrays are the wrong abstraction for shell scripts. Arrays are more or
less a mid-90's bolt-on.
Think lists. Remember that:
Any value containing spaces is a list. You can change the definition of
"space" using the special variable IFS.
The variable $* is a special list that acts a little like a stack. You
can set it with set:
$ set a b c
$ echo $*
a b c
$ shift; echo $* # pop
b c
$ set a $* # push
$ echo $*
a b c
Be careful:
$ X=
$ set $X
will give ugly results. The most portable workaround looks a little
like this:
$ set xx $X; shift
Um...
$ R=$(grep '^root' /etc/passwd | sed 's/[[:space:]]/_/g')
$ set $(IFS=:;echo $R)
$ echo $*
root x 0 0 root /root /bin/bash
$ echo $6
/root
So....
Send your key as the first arg and the list of items as the remaining
args:
SearchFor() {
declare K= ITEM="$1"; shift
declare LIST="$@"
declare -i N=1
for K in $LIST; do
if [ "$K" == "$ITEM" ];then
echo $N; return 0
fi
let N++
done
return 1
}
echo -e -n "enter a value to search for : "
read -e KEY
arr="f q e c d s a"
position=$(search_array "$KEY" $arr)
if [ -z "$position" ]; then
echo -e "the value "$KEY" is not in the array"
else
echo -e "the value "$KEY" was found at position: "$position
fi
exit 0
I of course did no testing....
HTH
ccb
More information about the Discuss
mailing list