-2

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.

Tim
  • 101,790
  • 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 00: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 06:53
  • @phi. Where does the manual say that parameter expansion is done before arithmetic expansion? – Tim Sep 27 '17 at 10:36
  • 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
  • @Philippos you misunderstood the meaning of "left-to-right" https://unix.stackexchange.com/a/270324/674. "brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution" have the same priority. – Tim Sep 27 '17 at 12:04
  • 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} – Chris Davies Sep 27 '17 at 12:14
  • Roaima is right. The order of evaluations is what is quoted by Philippos. As for "left-to-right", it does not specify the respective order of the different kinds of expansions, it specifies the evaluation order for each kind of expansion. Left-to-right means that ${undefined:=foo}${undefined} evaluates to foofoo whereas it would evaluate to foo if the evaluation was right-to-left. Likewise, left-to-right means that in $(cmd1)$(cmd2), cmd1 is executed before cmd2. – xhienne Sep 27 '17 at 12:39
  • 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

1 Answers1

3

You need either eval or indirection for this:

eval echo \${$((1+1))}
index=$((1+1))
echo ${!index}
Hauke Laging
  • 90,279
  • 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 00:37