views:

354

answers:

1

Why doesn't this work???

#!/bin/ksh

# array testfunc()
function testfunc {
    typeset -A env
    env=( one="motherload" )
            print -r $env
    return 0
}

testfunc # returns: ( one=motherload )
typeset -A testvar # segfaults on linux, memfaults on solaris 
testvar=$(testfunc) # segfaults on linux, memfaults on solaris
print ${testvar.one}

note: I updated the above script to print ${testvar.one} from print $testvar to show more precisely what I am trying to accomplish.

I am sure this has been asked before, but I am not sure what to search on and everything I have been trying to use for keywords is not bringing me any answers that relate to my problem.

ksh version:

linux: version sh (AT&T Research) 1993-12-28 s+

solaris: version sh (AT&T Research) 93s+ 2008-01-31

Update:

So another question is, this will run in ksh 93t+ without giving an error, but, it doesn't assign the array properly. I would I go about assigning an array from a function? I tried assigning the array like this also:

typeset -A testvar=$(testfunc)
print ${testvar.one}

But that also didn't work properly.

EDIT

So what is happening here?

typeset -A env=( one="motherload" two="vain" )
print ${env.one}
print ${env.two}

I thought this was how you defined associative arrays, maybe what I was looking at was old but who knows.... seems odd behaviour since this prints out "motherload" and "vain"

+1  A: 

Your script works fine for me on Linux with ksh 93t+.

Since it's the same script and you're getting similar errors in two different environments, I would suspect stray characters in the file. Try one of these to show any stray characters that might be present:

hd filename
cat -v filename
hexdump -C filename

If it's simply a matter of DOS line endings, then this will fix that:

dos2unix filename

Edit:

Here's one way to create and populate an associative array in ksh:

$ typeset -A testvar
$ testvar=([one]="motherlode" [two]="vein" [waste]="tailings")
$ echo ${testvar[two]}
vein
$ testvar[ore]="gold"
$ echo ${!testvar[@]}    # print the indices of the array
one two waste ore
$ typeset -p testvar     # show the current definition of the array
typeset -A testvar=([one]="motherlode" [two]="vein" [waste]="tailings" [ore]="gold")

As you can see, ksh uses bracketed subscripts for arrays. Dotted notation is used for accessing members of a compound variable.

I don't believe ksh functions can return arrays. However, you can use the print technique you have in your function (but add square brackets around the index name) and use eval to do the assignment.

$ typeset -A testvar 
$ eval "testvar=($(testfunc))"

or to append to an existing array:

$ eval "testvar+=($(testfunc))"

Unless your function is using associative arrays internally, you don't necessarily need to use them to build your output.

However, if you do, you can parse from the result of typeset -p:

$ result=$(typeset -p env)
$ result=${result#*\(}
$ result=${result%\)*}
$ print result

or iterate through the array:

$ for index in ${!env[@]}; do print -n "[$index]=${env[$index]} "; done; print

You may want to consult the documentation concerning discipline functions and type variables

Dennis Williamson
Okay so it works for me also on ksh 93t+... looks like this was an issue in previous <93s+ versions...
rcarson
actually it just doesn't error, it does not provide the results I was looking for.
rcarson
So what exactly am I doing here? < see edit >
rcarson