4

I want to construct variable name N_foo and N_bar and use their values in the following:

#!/bin/bash
N_foo=2
N_bar=3
for i in { "foo" "bar" }
do
    for j in { 1..$(`N_$i`) }
    do
        echo $j
    done
done

I want to use the values of N_foo and N_bar in the two inner loops and print out 1, 2 and 1, 2, 3, respectively. What's the correct syntax?

2
  • first youll have to remove the { } from outer for and remove space next to the {} in inner loop. echo { 1..3 } does not produce what you want. Commented Jul 1, 2011 at 3:40
  • arrays are the best way to avoid this kind of "eval" hell. What are you actually trying to do? Commented Jul 1, 2011 at 4:06

4 Answers 4

8
#!/bin/bash
N_foo=2
N_bar=3
for i in "foo" "bar"
do
    key="N_${i}"
    eval count='$'$key
    for j in `seq 1 $count`
    do
        echo $j
    done
done
Sign up to request clarification or add additional context in comments.

3 Comments

eval is the classic solution to this sort of issue.
@Computist: I rejected the edit you made to this answer. The answer didn't use the ${!symbol} syntax you are asking about. Your edit is really a new question. If you decide not to open a new question for it, you should edit your own question instead of the answer.
Notice that you do not need the inner loop -- seq 1 $count is enough.
6

You can use the indirect variable reference operator:

Example

var="foo"
nfoo=1
ref=n${var}
echo $ref
echo ${!ref}

Which gives this output:

nfoo
1

1 Comment

Ignacio: Yeah you're right - didn't work like I expected it to when used in the for loop range braces. {1..${!var}} didn't create a range like I thought it would....
5
#!/bin/bash
N_foo=2
N_bar=3
for i in "foo" "bar"
do
    i2="N_$i"
    seq 1 ${!i2}
done

2 Comments

Much better (and concise than the accepted answer). Thank you.
Not sure about "better" -- seq is nonportable, not specified by POSIX nor included as part of bash.
0

I ended up using the following code. It uses the parameter substitution technique (c.f. http://tldp.org/LDP/abs/html/parameter-substitution.html).

#!/bin/bash
N_foo=2
N_bar=3
for i in "foo" "bar"
do
j_max=N_$i
for (( j=1;  j<=${!j_max}; j++ ))
    do
    echo $j
    done
done

The ! is history expansion parameter (c.f. http://www.gnu.org/software/bash/manual/bashref.html#Special-Parameters). !j_max will be replaced by the most recent value set to j_max which is N_foo/N_bar in 1st/2nd iteration. It then calls ${N_foo}/${N_bar} which has value 2/3 in the 1st/2nd iteration.

1 Comment

Please avoid linking to the ABS -- it's the W3Schools of bash, full of bad-practice examples and outdated content. Consider the bash-hackers' wiki on indirection, or BashFAQ #6.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.