7

I am trying to print a simple value for $AR1_p1 but the variable $i is not evaluating.

for i in 1 2 3 4
do
AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p3=25
echo $AR1_p$i
done 

It's like concatenating dynamically. Any suggestions on how to fix this?.

migrated from serverfault.com Jan 17 '16 at 10:15

This question came from our site for system and network administrators.

  • 1
    Perhaps the echo line should be: echo $AR1_p1$i – parkamark Jan 12 '16 at 13:50
  • @parkamark, I want this to be dynamic like p1,p2 etc. – serverliving.com Jan 12 '16 at 13:52
  • 2
    You should use arrays instead. What you want is not possible (or at least very bad style). – Sven Jan 12 '16 at 13:53
  • @Sven, I understand i can use arrays but since i have only 4 values to evaluate. So this is a problem with bash ?. – serverliving.com Jan 12 '16 at 13:55
  • @serverliving.com no, this is not a problem with Bash. Bash is behaving exactly the way it should, and this is indeed an issue for which it makes sense to use an array. Why is it an issue to use an array of 4 elements? – Jules Jan 12 '16 at 16:57
6

This loop works. Else use Arrays.

$ for i in 1 2 3 4; do AR1_p1=22; AR1_p2=23; AR1_p3=24; AR1_p4=25; echo $((AR1_p$i)); done 
22
23
24
25
  • 1
    Note this will only work for integer-valued parameters. – chepner Jan 21 '16 at 1:01
23

You can use bash indirect references for that:

AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p4=25
for i in 1 2 3 4
do
  VARNAME="AR1_p${i}"
  echo "${!VARNAME}"
done
7

Per suggested comment(s), array should be used:

#!/bin/bash

AR1_p=(22 23 24 25)

for i in {1..4}
do
  echo "${AR1_p[$i-1]}"
done
  • This doesn't make any sense. The for loop is an array assignment already... – mikeserv Jan 21 '16 at 1:44
  • You are correct, it doesn't make any sense. As much as this has had up votes, it didn't fully address the true requirement of the original question. That was addressed in the other answer above relating to "bash indirect references" which is a better solution for what the OP was trying to achieve. My post does, however, demonstrates some of the intricacies that can be employed in BASH to achieve the same thing, noting that the above could simply be reduced to "for i in {22..25}; do echo $i; done", but that answer doesn't really have any relevance to the original question. – parkamark Jan 21 '16 at 9:30
3

Use eval:

#!/bin/bash

AR1_p1=22
AR1_p2=23
AR1_p3=24
AR1_p4=24
for i in 1 2 3 4
do
    eval echo \$AR1_p$i
done

echo expands only $i. When this expression reaches eval, it is like : $AR1_p1. Eval tries to evaluate and gives the result.

  • 6
    eval is usually a bad idea. In this example of course you aren't handling external input, but if you ever do you need to be very sure you sanitize any data you pass to eval. (Which is hard. Very hard. Better to just skip it.) – Wildcard Jan 12 '16 at 16:22
  • 1
    @Wildcard - it isn't all that hard, really. And learning how to do it the right way shouldn't be skipped. – mikeserv Jan 21 '16 at 1:33
1

POSIXly:

for i in 1 2 3 4
do  AR1_p1=22
    AR1_p2=23
    AR1_p3=24
    AR1_p4=25
    echo "$((AR1_p$i))"
done

A little less messy, maybe:

for i in 1 2 3 4
do  echo "$((AR1_p$i=i+21))"
done

Still POSIXly, but far more sensible:

i=0 n=21 l=4
while  [ "$l" -ge "$((i+=1))" ]
do     echo "$((AR1_p$i=i+n))"
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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