The UNIX and Linux Forums  

Go Back   The UNIX and Linux Forums > Top Forums > Shell Programming and Scripting
Google UNIX.COM


Shell Programming and Scripting Post questions about KSH, CSH, SH, BASH, PERL, PHP, SED, AWK and OTHER shell scripts here.

More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
Array inside an array manas_ranjan UNIX for Advanced & Expert Users 5 06-10-2008 11:25 AM
ksh93 deprecation... curleb Shell Programming and Scripting 2 03-17-2008 05:36 PM
create array holding characters from sring then echo array. rorey_breaker Shell Programming and Scripting 5 09-28-2007 05:42 AM
Exception Handling bertpereira Shell Programming and Scripting 4 05-24-2007 10:39 AM
Using subsring in ksh93 - How to stuff a byte back in The Doctor Shell Programming and Scripting 2 03-25-2006 09:27 PM

Reply
 
Submit Tools LinkBack Thread Tools Display Modes
  #1  
Old 10-20-2005
Bughunter Extraordinaire
 

Join Date: May 2005
Location: In the leftmost byte of /dev/kmem
Posts: 1,235
Strange array handling in ksh93

I wrote a script in ksh93 (the OS is AIX 5.2, ML7), which failed to run. After some testing i found out why, but the answer is a bit dissatisfying. Look for yourself:

Code:
#!/bin/ksh93

# --------- Step Names
typeset achStepName[1]="foo"
typeset achStepName[2]="bar"
typeset achStepName[3]="fubar"
typeset achStepName[4]="test"

(( iCnt = 1 ))
while [ $iCnt -le ${#achStepName[@]} ] ; do
     print - $iCnt ${achStepName[$iCnt]}
     (( iCnt += 1 ))
done

exit 0
One would expect this to give a little table with the entries 1, 2, 3 and 4, just like the array is defined. Instead the output looks like:

Code:
1
2 bar
4 fubar
4 test
The reason is, that "foo" will somehow become the array element with the index "0"! After modifying the code to start the loop with iCnt=0 the output table looked like:

Code:
0 foo
1
2 bar
4 fubar
4 test
Has anybody a good explanation of this and a way to avoid that? Have I done something wrong?

To be honest, i can't believe a bug that big making it beyond alpha-testing, lest production.

bakunin
Reply With Quote
Forum Sponsor
  #2  
Old 10-22-2005
Perderabo's Avatar
Unix Daemon
 

Join Date: Aug 2001
Location: Washington DC Area
Posts: 8,611
Wow! The problem all lies here....
Code:
typeset achStepName[1]="foo"
typeset achStepName[2]="bar"
typeset achStepName[3]="fubar"
typeset achStepName[4]="test"
This is actually the screwiest ksh code that I have ever seen. I have to say that I didn't know what behavior to expect. I have just reread "The New KornShell" by Bolsky and Korn. I don't believe that Dave Korn ever anticipated code like that. When I run your code in my ksh , I get the results that you want, not the results that you get. That may or may not be good thing. If I change your "typeset" to be "typeset -R9", I suddenly do get the results you are getting.

A variable in ksh starts life out as a scalar but it later may be promoted to an array. If a variable is promoted to an indexed array and it had a value, that value is retained as element zero. So
var="first"
var[1]="second"
echo ${var[0]}
will result in "first" being echoed.

Now a typeset statement can do 2 things to a variable: assign it a value; and assign it a type. The documentation implies that these operations will be done in that order. This is to support the read-only attribute with a statement like:
typeset -r var="locked value"
Part of what a typeset statement can do is to promote a scalar to an indexed array. The syntax for that is:
typeset variable[5]
This statement variable into an array and also makes the claim that it has 5 elements. Since an array starts with 0, the last possible element is 4. Apparently, ksh does not enforce that limit, so it is for documentation only.

Your first statement:
typeset achStepName[1]="foo"
almost actually makes sense. First you assigned:
achStepName="foo"
then you declared that achStepName is an array with a single element. The only valid index for an array a single element is 0.

Now your next statement:
typeset achStepName[2]="bar"
Well, I really can't tell you what this should do. The statement seems to be self-inconsistent. We seem to be claiming that achStepName now has two elements. If so, they would be 0 and 1. We are also assigning a value... but to what? The third element of our two element array? That seems to be how the interpreters are behaving.

Here is something interesting, the statement:
typeset -Z9 zeros[7]=123
affects zeros[0] the first time it is executed and zeros[7] the second time it is executed. I feel that it should do the same thing both times. Since that is not the case, I must agree that ksh has a bug. I have been programming in ksh for quite a while without encountering this before. So I still do not agree that this bug should have been caught in alpha-testing.
Reply With Quote
  #3  
Old 10-24-2005
Bughunter Extraordinaire
 

Join Date: May 2005
Location: In the leftmost byte of /dev/kmem
Posts: 1,235
Hmm....

Actually i didn't know all that about variable handling in the ksh, so many thanks for explaining this.

On the other hand, in ksh(88) the code works as expected: the four statements generate a table with four elements and indices 1,2,3,4. The expression ${#table[@]} evaluates to 4 and the loop works fine.

I tried this now on another machine (AIX 5.1, ML06) and there it worked to what i would have expected too.

As I have understood my ksh manual "arr[n]" not only sizes an array but also denotes a specific array element. Otherwise the expression "print - "${arr[3]}" wouldn't make sense, right?

Further, the ksh93 man page states, that ksh93 now has "associative arrays" and i don't see the difference between "arr[tommy]", "arr[willy]" and "arr[1]". Since the first two values will not (for obvious reasons) be zero-based, why has the latter one to be?

bakunin
Reply With Quote
  #4  
Old 10-24-2005
Perderabo's Avatar
Unix Daemon
 

Join Date: Aug 2001
Location: Washington DC Area
Posts: 8,611
Retry all of those version of ksh using something like "typeset -Z9 zeros[7]=123". You will probably find that the 2 statements:
typeset -Z9 zeros[7]=123
typeset zeros[7]=123
work differently. And remember, "zeros" must be undefined to see the difference. On your ksh93 the two statements will both set zeros[0]=123 on the first execution. And they both will set zeros[7]=123 on the second execution.

What arr[n] does depends on where it is used. There is no language on the ksh93 man page stating that an array reference is allowed at all in a typeset statement. Only is the ksh book is there some fleeting mention of using typeset vname[n] to declare an indexed array.

Why do indexed arrays need to start with zero? Because that is way the language works. Dave Korn could have decreed that they start with 1 or even 719. He picked 0, probably because C does. Without a standard, stuff like:
array=(aaa bbb ccc)
set -A array aaa bbb ccc
would not make sense. ksh93 has blurred the distinction bewteen associative arrays and indexed arrays as much as is possible. I am disaapointed with that particular design choice and it is adding to the confusion here. You seem to have lost the concept entirely. I hope this isn't because your ksh93 is broken. Try this:
x[2]=7
x[1+1]=9
echo ${x[2]}
typeset -A x
x[2]=7
x[1+1]=9
echo ${x[2]}
When I run this, I get 9 the first time and 7 the second.
Reply With Quote
Google The UNIX and Linux Forums
Reply

Thread Tools
Display Modes




All times are GMT -7. The time now is 05:54 AM.


Powered by: vBulletin, Copyright ©2000 - 2006, Jelsoft Enterprises Limited.
The UNIX and Linux Forums Content Copyright ©1993-2008. All Rights Reserved.Ad Management by RedTyger Visit The Complex Event Processing Blog

Content Relevant URLs by vBSEO 3.2.0