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