Results 1 to 6 of 6
Greetings.
I just joined this forum (so new that I have not been able to post an avatar yet.) I recently posted this question on the Ubuntu forum (with a ...
- 11-21-2011 #1Just Joined!
- Join Date
- Nov 2011
- Location
- Brooklyn, NY (USA)
- Posts
- 4
Indirect reference works once only
Greetings.
I just joined this forum (so new that I have not been able to post an avatar yet.) I recently posted this question on the Ubuntu forum (with a misspelled reference
)and got no helpful response. I hope this forum has more daring readers. It ain't short but a complicated question can't be asked in 30 words. OK, Here goes:
-----------------------------------------------------------
I have recently started trying to use indirect references in ksh93. That is, when I set variable-b to the name of variable-a and obtain the value of variable-a by dereferencing variable-b. (Sorta like pointers.)
I have been able to make it work but not in the manner I had expected. I'm hoping someone can point out my flaw.
Let's start with my "control" script, where I have made no real effort to use the indirect reference.
(The missing line numbers are where I have removed commented code)Code:1 #!/bin/ksh 2 # 3 4 one=1 5 two=2 6 three=3 7 four=4 8 five=5 9 10 for DIGIT in one two three four five 11 do 12 NUMBER=$DIGIT 14 echo $DIGIT ${NUMBER} 15 done
Here is the output of that:
This is very much as expected.one one
two two
three three
four four
five five
Now let's declare NUMBER to be an indirect reference:
The output of this attempt is:Code:1 #!/bin/ksh 2 # 3 typeset -n NUMBER 4 one=1 5 two=2 6 three=3 7 four=4 8 five=5 9 10 for DIGIT in one two three four five 11 do 12 NUMBER=$DIGIT 14 echo $DIGIT ${NUMBER} 15 done
Hey, it worked only the first time! After that it gave me the names I threw into it instead of chasing down the values behind those names.one 1
two two
three three
four four
five five
OK, what happens if I repeat the typeset command each time around the loop. If I do this I don't need to do it on line 3. Here goes:
And the output of that is:Code:1 #!/bin/ksh 2 # 3 #typeset -n NUMBER 4 one=1 5 two=2 6 three=3 7 four=4 8 five=5 9 10 for DIGIT in one two three four five 11 do 12 NUMBER=$DIGIT 13 typeset -n NUMBER=$DIGIT 14 echo $DIGIT ${NUMBER} 15 done
AHA! THAT'S the output I was looking for! But it annoys me that I should need to repeat the typeset command for every new string name [of a variable] to which I set NUMBER. It looks like one typeset declaration is not enough.one 1
two 2
three 3
four 4
five 5
Is there some way I can use one typeset directive and have it last the duration of the script? BTW, using the nameref directive wasn't any more successful. I was trying to mimic the examples in Bolsky and Korn's book The New KornShell Command And Programming Language (2nd Edition) but the examples there are more on using associative arrays of namerefs. Powerful and useful as those are, my example was trying to keep it simple for my first foray into the use of namerefs.
Thanks much for advice. This will affect the nature of shell scripts I am planning.
__________________
-- Rasputin Paskudniak II (In pursuit of undomesticated, semi-aquatic avians)
- 11-23-2011 #2
My first advice to you is to use bash, not ksh. ksh is almost never used anymore, and there are not nearly as many resources as there are for bash. bash is essentially the standard shell now, with zsh becoming popular in some circles.
Anyway, based on the research that I have been able to do, this is basically expected behavior. Unlike, for instance, bash's typeset, ksh's "typeset -n" appears to indicate that THIS ASSIGNMENT is a reference assignment. bash's typeset (and perhaps other ksh typesets, I do not know) sets properties of the variable, not particular assignments, and references use a different syntax.
So when you say "typeset -n NUMBER=$DIGIT", you are saying "make NUMBER be a reference to DIGIT". But then when you later say "NUMBER=$DIGIT", you are saying "set NUMBER to the value of DIGIT".
Does this make sense?DISTRO=Arch
Registered Linux User #388732
- 11-23-2011 #3Linux Engineer
- Join Date
- Apr 2006
- Location
- Saint Paul, MN, USA / CentOS, Debian, Solaris, SuSE
- Posts
- 1,117
Hi.
I look at this based on the description:
which suggests that this is a property of the nameref, but that the action is essentially static -- whatever is the current value of variable will be the name of the variable that will be the value supplied when the nameref is used. From this perspective, the result posted by the OP is what I would expect -- i.e. that the typeset is needed to cause a new value to be set. Perhaps this is a re-phrase of the reply from cabhan, but it seems different to me.A
nameref is created with the -n attribute of typeset. The value of the
variable at the time of the typeset command becomes the variable that
will be referenced whenever the nameref variable is used.
-- excerpt from man ksh
Minor quibble with:
There are many people over at unix.com who would disagree with that statement. Having said that, there probably are more people that use bash than use ksh, making it somewhat more likely to be able to get help with bash as opposed to ksh. The entry at Korn shell - Wikipedia, the free encyclopedia suggests that David Korn still supports it. Development of ksh certainly seems to be slow if not stopped when compared to bash.
Originally Posted by Cabhan
There is an interesting Q and A with Korn at David Korn Tells All - Slashdot
Best wishes ... cheers, drlWelcome - get the most out of the forum by reading forum basics and guidelines: click here.
90% of questions can be answered by using man pages, Quick Search, Advanced Search, Google search, Wikipedia.
We look forward to helping you with the challenge of the other 10%.
( Mn, 2.6.n, AMD-64 3000+, ASUS A8V Deluxe, 1 GB, SATA + IDE, Matrox G400 AGP )
- 11-23-2011 #4Linux Engineer
- Join Date
- Apr 2006
- Location
- Saint Paul, MN, USA / CentOS, Debian, Solaris, SuSE
- Posts
- 1,117
Hi.
By accident, I noticed this in the ksh man page on nameref:
which would lead to something like this:If a nameref is used as the index of a for loop, a name
reference is established for each item in the list.
producing:Code:#!/usr/bin/env ksh # @(#) s1 Demonstrate special case for-loop property of ksh nameref. # Utility functions: print-as-echo, print-line-with-visual-space, debug. # export PATH="/usr/local/bin:/usr/bin:/bin" pe() { for _i;do printf "%s" "$_i";done; printf "\n"; } pl() { pe;pe "-----" ;pe "$*"; } db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; } db() { : ; } C=$HOME/bin/context && [ -f $C ] && . $C pe one=1 two=2 three=3 four=4 five=5 for DIGIT in one two three four five do NUMBER=$DIGIT echo $DIGIT ${NUMBER} done pe nameref DIGIT for DIGIT in one two three four five do NUMBER=$DIGIT echo $NUMBER done exit 0
Best wishes ... cheers, drlCode:% ./s1 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64 Distribution : Debian GNU/Linux 5.0.8 (lenny) ksh 93s+ one one two two three three four four five five 1 2 3 4 5
Welcome - get the most out of the forum by reading forum basics and guidelines: click here.
90% of questions can be answered by using man pages, Quick Search, Advanced Search, Google search, Wikipedia.
We look forward to helping you with the challenge of the other 10%.
( Mn, 2.6.n, AMD-64 3000+, ASUS A8V Deluxe, 1 GB, SATA + IDE, Matrox G400 AGP )
- 11-27-2011 #5Just Joined!
- Join Date
- Nov 2011
- Location
- Brooklyn, NY (USA)
- Posts
- 4
Dear DRL,
You have helped me tremendously by noticing that remark stuck in the haystack of the ksh man page. It took me a few minutes of scrolling up and down this thread before I saw the difference between your code and my example #2, where it worked only for the first round of the loop. Otherwise, I will indeed need to use an explicit typedef -n (or nameref). So my question is answered to my satisfaction, if not the perfect manner I was hoping for.
As to cabhan's suggestion that I switch to bash: Many scripts I have written use the construct:
<some program that generates many similar lines> | while read A B C D E
do
<huge stuff>
done.
This works in ksh but barfs at me like an infant sibling in bash. I posted my issue with bash in January on the Ubuntu Forum. So bash is out of my equation. BTW< I am constrained from posting the URL of that thread because I am too new to this forum. However, the thread title is "bash read command not assigning the target variables", originally posted 2011-01-02.
Now how do I mark this thread "Solved"?
Again, thanks drl. And cheers back across the pond.
-- Rasputin Paskudniak (In pursuit of undomesticated, semi-aquatic avians)
- 11-27-2011 #6Linux Engineer
- Join Date
- Apr 2006
- Location
- Saint Paul, MN, USA / CentOS, Debian, Solaris, SuSE
- Posts
- 1,117
Hi, rpaskudniak.
Two comments:
1) You might want to look over the thread at korn shell variable help for another method of handling lists, namely arrays.
2) The bash property of creating a separate scope for a pipe-into-loop situation can be avoided by using a special bash syntax. The script below will attempt to perform 2 loops, 1 piping in at the top, the other re-directing from the bottom. The results are for sh, ksh, and bash:
producing for sh (linked to bash, but doing things sh-like):Code:#!/usr/bin/env sh # @(#) s4 Demonstrate re-direct input at bottom of loop. # Utility functions: print-as-echo, print-line-with-visual-space, debug. # export PATH="/usr/local/bin:/usr/bin:/bin" pe() { for _i;do printf "%s" "$_i";done; printf "\n"; } pl() { pe;pe "-----" ;pe "$*"; } db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; } db() { : ; } C=$HOME/bin/context && [ -f $C ] && . $C n=0 lines=0 pl " Results, pipe into while at top, n = $n, lines = $lines" seq 5 | wc -l | while read n do pe " In loop, number of sequences is $n" lines=$n done pl " Outside loop, n is $n, lines is $lines" n=0 lines=0 pl " Results, pipe into while at bottom, n = $n, lines = $lines" while read n do pe " In loop, number of sequences is $n" lines=$n done < <( seq 5 | wc -l ) pl " Outside loop, n is $n, lines = $lines" exit 0
producing with ksh:Code:% ./s4 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64 Distribution : Debian GNU/Linux 5.0.8 (lenny) GNU bash, version 3.2.39(1)-release (x86_64-pc-linux-gnu) ----- Results, pipe into while at top, n = 0, lines = 0 In loop, number of sequences is 5 ----- Outside loop, n is 0, lines is 0 ----- Results, pipe into while at bottom, n = 0, lines = 0 ./s4: line 32: syntax error near unexpected token `<' ./s4: line 32: `done < <( seq 5 | wc -l )'
noting that ksh does not understand the special sequence, but bash produces:Code:% ksh s4 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64 Distribution : Debian GNU/Linux 5.0.8 (lenny) ksh 93s+ ----- Results, pipe into while at top, n = 0, lines = 0 In loop, number of sequences is 5 ----- Outside loop, n is , lines is 5 ----- Results, pipe into while at bottom, n = 0, lines = 0 s4: line 27: syntax error at line 32: `<(' unexpected
noting that bash fails on the pipe-in-from-top loop, but succeeds with the special syntax re-directing in from the bottom (spaces in "< <(" are necessary)Code:% bash s4 Environment: LC_ALL = C, LANG = C (Versions displayed with local utility "version") OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64 Distribution : Debian GNU/Linux 5.0.8 (lenny) GNU bash 3.2.39 ----- Results, pipe into while at top, n = 0, lines = 0 In loop, number of sequences is 5 ----- Outside loop, n is 0, lines is 0 ----- Results, pipe into while at bottom, n = 0, lines = 0 In loop, number of sequences is 5 ----- Outside loop, n is , lines = 5
Best wishes ... cheers, drlWelcome - get the most out of the forum by reading forum basics and guidelines: click here.
90% of questions can be answered by using man pages, Quick Search, Advanced Search, Google search, Wikipedia.
We look forward to helping you with the challenge of the other 10%.
( Mn, 2.6.n, AMD-64 3000+, ASUS A8V Deluxe, 1 GB, SATA + IDE, Matrox G400 AGP )


Reply With Quote