Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I am new to Unix shell scripting My code is as follows:

  i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[i]=var
  ((i=`expr i+1`))
done
a=10
b=50
c=40
d=90
e=100
Now I wanted to print the local variables contents using array into the function

print_array
{
echo "${content[0]}"
echo "${content[1]}"
echo "${content[2]}"
echo "${content[3]}"
echo "${content[4]}"
} 

what I wanted to do that array contents are {a,b,c,d,e} and there is a local variables named a,b,c,d,e with some assigned values I wanted to print those local variables through the use of array since the name of array element and local variable element is same so I tried to call by reference by trying multiple combinations of $ and array_names but not working

share|improve this question

3 Answers 3

up vote 1 down vote accepted

So I'll define an indirect printing function first...

_print() while [ "$#" -ne 0 ]
         do    printf '$%s = %d\n' \
                       "$1" "$(($1))"
               shift
         done

Next I'll setup the array and increment...

arr=( a b c d e ); i=0
for var in "${arr[@]}"
do  : "$(($var=(i+=10)))"
done

So now the value of $a is 10 and $b 20 and so on. Last there remains only to print...

_print "${arr[@]}"

...which prints to stdout...

$a = 10
$b = 20
$c = 30
$d = 40
$e = 50

All of this works because of the way the shell handles $((math)) expansions - they're basically evals. In an arithmetic expansion the shell first expands any other valid shell expansion before attempting to do the math - making the actual math its last order of business.

This means that if you do:

i=a a=10; echo "$(($i))" 

The printed result is 10 because the shell expands the value of $i to get a then evaluates that result as an integer reference.

The above will work in any POSIX-compliant shell.

This means I could possibly also have done...

i=10
for var in a b c d e
do  arr[($var=i*${#arr[@]}+i)/i]=$var
done

...to handle array assignment, index evaluation, and $var integer assignment at once because the [index] brackets of a named shell array - in a shell which supports them - are treated identically to the $((expansion)) parens of a math expression.

Running the above code wrapped in ksh -xc command prints the following debug output to standard error:

+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e

From there I can just do:

echo "$((${arr[1]}))"
echo "$((a))"

...to print...

10
10

...because they evaluate to the same thing in shells which support named arrays. However, in shells which don't...

echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e)     #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected   #sh traces something else

So in the _print() function I just shift over the positional parameters (which represents a truly portable shell "$@"array) while there are any at all and printf...

  1. First a $ dollar sign.
  2. Then the %string value stored in my $1st positional parameter.
  3. Then an = equals sign.
  4. And last the value stored in the value stored in my $(($1)) first positional parameter.

As the function shifts its arguments away the first positional parameter is constantly being replaced with the next until the $# count of positionals equals 0 and the function returns.

Before running the function when I initialize the array and its constituent indirection variables that works like this:

  • for var in "${arr[@]}"

    • The shell will expand [@] to a list of arguments and [*] to a single concatenation of that list. If the expansion is not quoted it might also expand [*] out to a list as well - depending on whether or not there is a value for $IFS when it is done and how set -filename expansion is currently configured - but if it does so it likely does not do it the way you intend.
  • : "$(($var=(i+=10)))"

    • Each value in ${arr[@]} is assigned to the value of $var in turn. $(($var=(i+=10))) is then expanded first for the value in $var like $((a=(i+=10))) and last of all the math is done - which first increments $i by 10 and next assigns the value of $i to $a.
share|improve this answer
    
@mikerserv It is giving error 0403-057 Syntax error at line 6 : `(' is not expected. means at this line arr=( a b c d e ); i=0 then I have changed it to arr= 'a' 'b' 'c' 'd' 'e' then error message a: not found is coming please guide me to solve it thanks a lot for your descriptive answer :) –  Aman Apr 7 at 11:13
    
@Aman - a: not found sounds like you're trying to run a command. Which version of ksh? –  mikeserv Apr 7 at 11:49
    
I am running on bash 4.2 –  Aman Apr 7 at 13:28
    
@Aman - well, then you must have entered something in wrong - everything up there works in bash - at least it does on my system. Have you tried it since edited it? It shouldn't make a difference though... –  mikeserv Apr 7 at 14:15
    
I am going to retest it. –  Aman Apr 7 at 14:19

If I understand you correctly you want an indirection in variable's access with, e.g., bash. With this code:

content=( a b c d e )

a=10
b=50
c=40
d=90
e=100

echo "${!content[0]}"
echo "${!content[1]}"
echo "${!content[2]}"
echo "${!content[3]}"
echo "${!content[4]}"

You will get this result:

10
50
40
90
100

The key here is bash's specific variable expansion access method "${! ... }".

share|improve this answer
    
I have bash 4.2 which does not support echo "${!content[4]}" mentioned process substitution please guide me :) –  Aman Apr 7 at 17:43
    
@Aman; the construct that I proposed is certainly running even in old bash versions. In every proposed solution you claim you are running a bash and getting errors. So I have to say I have my doubts that what you say is true! - Try two things: bash --version, and (instead of calling your script as ./yourscript) call your script explicitly with bash yourscript. –  Janis Apr 8 at 6:31
    
@Aman; I just see in an analysis of another poster's answer that you are running sh and not bash. So use the form I proposed to call your script, bash yourscript, and everything should work fine. –  Janis Apr 8 at 6:38

Try

#i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[${#content[*]}]=$var  # or content[i++]=$var
done
# or just content=( 'a' 'b' 'c' 'd' 'e' )
a=10
b=50
c=40
d=90
e=100
for i in "${#content[@]}"
do
  echo ${!i}
done
share|improve this answer
    
Getting Error :${!i}: 0403-011 The specified substitution is not valid for this command. @Costas –  Aman Apr 7 at 9:57
    
@Aman bash -version ? I have GNU bash 4.3.11 –  Costas Apr 7 at 10:00
    
I have bash 4.2 –  Aman Apr 7 at 10:01
    
Try eval j=\$$i;echo $j (and I correct the code above var --> $var, so try it again) –  Costas Apr 7 at 10:06
1  
Try simple test a=b ; b=5 ; echo ${!a} and show output here –  Costas Apr 7 at 17:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.