-2

This question already has an answer here:

Please reopen. This is not a duplicate, because here I am asking why it doesn't work, not just for workaround.


Bash manual says that

tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion)

If I understand http://unix.stackexchange.com/a/270324/674 correctly, "left-to-right" means that "brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution" have the same priority.

So is it possible to use arithmetic expansion inside parameter expansion? (i.e. one level recursion)

If no, why can't arithmetic expansion work inside parameter expansion, given that "tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion)"?

If yes, how?

For example,

$ set hello world
$ echo $2
world
$ echo ${$((1+1))}
bash: ${$((1+1))}: bad substitution

I hope to

  • first expand $((1+1)) in ${$((1+1))} to 2. and
  • then ${2} to world.

Thanks.

marked as duplicate by αғsнιη, Stephen Rauch, Satō Katsura, Kusalananda bash Sep 27 '17 at 6:53

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    Because that's not left-to-right. What you're hoping for is not left-to-right. The documentation says expansion is done left-to-right. You want something else, I don't know what to call it; maybe "from-inside-to-outside" parsing? Please read the documentation and clear the English words in it like "left-to-right" so you can answer your own questions. (This question contains its own answer.) – Wildcard Sep 27 '17 at 0:40
  • What the manual tries to say is: parameter expansion is done before arithmetic expansion, so it works the other way around: set 6 7; echo $(($1*$2)) will work as expected. – Philippos Sep 27 '17 at 6:53
  • 3
    The whole sentence of your citation is: "The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion. – Philippos Sep 27 '17 at 10:44
  • 3
    @Tim they don't (and can't) have the same priority. Parameter expansion is done before arithmetic expansion, so $(( 1 + ${a:-5} )) will work but ${ $((1 + 1)) } won't. To solve your requirement you would need set 4 5; b=$((1+1)); echo ${!b} – roaima Sep 27 '17 at 12:14
  • 1
    Just to add more confusion in Tim's head, ${@:$((1+1)):1} would work though ;-) Hint: ${@:1+1:1} would work too. – xhienne Sep 27 '17 at 12:51
3

You need either eval or indirection for this:

eval echo \${$((1+1))}
index=$((1+1))
echo ${!index}
  • Thanks. I understand the two ways you mentioned. Why can't arithmetic expansion work inside parameter expansion, given that "tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion)"? – Tim Sep 26 '17 at 23:42
  • 2
    @Tim, because that wouldn't be left-to-right. – Wildcard Sep 27 '17 at 0:37

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