Operating System - HP-UX
1748137 Members
3554 Online
108758 Solutions
New Discussion юеВ

sh-posix: passing of arrays to functions

 
SOLVED
Go to solution
Ralph Grothe
Honored Contributor

sh-posix: passing of arrays to functions

Hi,

this isn't a real problem, just some syntactic sugar.
So that DBAs can read my scripts I'm refraining from Perl, and discover painfully many shell shortcomings.
Is it possible to pass arrays to functions, whose elements exceed the 9 psitional parameters without the need of shifting
(or is there such thing as passing of refs)?

I want to pass a number of files to a function that I derive from shell filename expansion (aka globbing), like such

# set -A files /app/bms/bin40/l[01][0-9][!WZ].dbg

# echo ${#files[*]}
56

Of course this won't yield what I expect

func_to_munch_files ${files[*]}

since shell will expand the 56 elements prior to passing.

Possibly yet another pseudo problem of a Perl-pampered occassional shell scriptor?

Madness, thy name is system administration
7 REPLIES 7
Muthukumar_5
Honored Contributor

Re: sh-posix: passing of arrays to functions

We can pass the array to function as by example,

#!/usr/bin/sh
set -x

fun()
{

set -A ARR $*

# Index
i=0

while [[ $i -lt ${#ARR[*]} ]]
do

echo ${ARR[$i]}

# Or some operation

let i=i+1

done

# Return
return 0

}

# Main function here
ARRAY="test ok bye for now 1 2"
fun ${ARRAY[*]}

It will work there easily.
Easy to suggest when don't know about the problem!
Muthukumar_5
Honored Contributor

Re: sh-posix: passing of arrays to functions

We can also use $@ on $* the collection of array information on the function's.
See the difference on ksh man page ( search $@ )

#!/usr/bin/sh
set -x
list()
{
set -A arr $@

i=0
while [[ $i -lt ${#arr[*]} ]]
do

echo ${arr[$i]}

let i=i+1

done

return 0

}

# Enter directory
echo " Directory -->"
read dir

if [[ -d $dir ]]
then
echo "Directory not found"
exit 1
fi
set -A AR `ls $dir`

list ${AR[*]}

# Exit
exit 0

Above script will list the files on the input give directory there.
Try and let know the problem if you have
Easy to suggest when don't know about the problem!
Muthukumar_5
Honored Contributor

Re: sh-posix: passing of arrays to functions

Sorry again,

what are you are trying here,

# set -A files /app/bms/bin40/l[01][0-9][!WZ].dbg

Are you assiging files with app/bms/bin40/l[01][0-9][!WZ].dbg format there???

there try as,

# set -A files $(ls /app/bms/bin40/l[01][0-9][!WZ].dbg)


# echo ${#files[*]}
56


And sheel operation says as,
# set -A files /app/bms/bin40/l[01][0-9][!WZ].dbg
# echo ${files[*]}
/app/bms/bin40/l[01][0-9][!WZ].dbg
# echo ${#files[*]}
1

So change the one more
Easy to suggest when don't know about the problem!
John Palmer
Honored Contributor
Solution

Re: sh-posix: passing of arrays to functions

Hi Ralph,

There's no issue with supplying more than 9 parameters to a function although there will be a limit based on memory size.

As to passing of refs, you could try using eval...

Example, you have an array called FILES and a function called munch_files. Your function call will be of the form:
munch_files FILES

The function could do something like this although I'm not able to test it...
function munch_files {
eval let NUMFILES=${#${1}[*]}
let I=0
while (( I < NUMFILES));
do
eval whatever you like with ${${1}[I]}
let I=I+1
done
}

It's a bit complicated though, not easy to tell what's going on. I reckon your average DBA would struggle with it ;-)

Regards,
John
Ralph Grothe
Honored Contributor

Re: sh-posix: passing of arrays to functions

Hi Muthukumar,

your command substitution with the additional ls isn't necessary.
The shell globbing works since the files exists.
However shell funcs don't seem to be designed for long lists of parameters.
I exercised the below on the command line where I have HP-UX's /usr/bin/sh as login shell (I think it's better than the Korn shell, but not as nice as Bash ;-)

# list() { set -A ary $*;i=0;while [[ $i < ${#ary[*]} ]];do echo ${ary[$i]};((i+=1));done; }

# typeset -f list
function list
{
set -A ary $*;i=0;while [[ $i < ${#ary[*]} ]];do echo ${ary[$i]};((i+=1));done; }

# set -A files /app/bms/bin40/l[01][0-9][!WZ].dbg

# echo ${#files[*]}
56

# echo ${files[*]}|tr '\040' '\012'|tail -10
/app/bms/bin40/l11O.dbg
/app/bms/bin40/l11T.dbg
/app/bms/bin40/l12A.dbg
/app/bms/bin40/l12B.dbg
/app/bms/bin40/l12O.dbg
/app/bms/bin40/l12T.dbg
/app/bms/bin40/l13A.dbg
/app/bms/bin40/l13B.dbg
/app/bms/bin40/l13O.dbg
/app/bms/bin40/l13T.dbg


# list ${files[*]}
/app/bms/bin40/l00A.dbg
/app/bms/bin40/l00B.dbg
/app/bms/bin40/l00O.dbg
/app/bms/bin40/l00T.dbg
/app/bms/bin40/l01A.dbg
/app/bms/bin40/l01B.dbg


Madness, thy name is system administration
Hein van den Heuvel
Honored Contributor

Re: sh-posix: passing of arrays to functions

Brute force it?...

Stick the elements in a (temp)file one line per name and pass the (temp)file?

Makes for easy debug / checking.
Just don't delete the (temp)file and you can see what you asked the script to work on.

Like you say, it's easy and clean in Perl! :-).

fwiw,
Hein.
Ralph Grothe
Honored Contributor

Re: sh-posix: passing of arrays to functions

John,

I'm sure your eval-ing will work.
But as you said, this is getting a bit too obfuscated (then I could have sticked to Perl ;-)

Hein,

I wouldn't want to park data in a temporary file (although the mktemp command would be reasonably safe), why would I try to use arrays then?
But if the No. of files was approching 1024 the globbing wouldn't be such a good idea anymore.
Also as John said the shell is soon reaching its limitation as far as word splitting is concerned (or characters with long path names).
I think I have to get used to global scoping in the shell (something you really feel uneasy about once you got accustomed to lexikal scoping and the strict pragma in Perl), and avoid any passing of longer lists of arguments to shell functions.
Madness, thy name is system administration