11

I want to dynamically create a sequence of strings by manipulate an array of elements and create some arithmetic procedure.

for name in FIRST SECOND THIRD FOURTH FIFTH; do
    $name = $(( $6 + 1 ))
    $name = "${$name}q;d"
    echo "${$name}"; printf "\n"
done

The desire outcome would be the below for $6 equals 0.

1q;d
2q;d
3q;d
4q;d
5q;d

But I get this error

reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution

I guess it's something simple. It used to work when I did something like

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"
  • 1
    Can you explain it little better. Don't really understand what are you trying to do. – neuron Aug 11 '15 at 11:31
  • What is ` $name = $(( $6 + 1 ))` supposed to do? – PSkocik Aug 11 '15 at 11:48
  • @PSkocik I was hoping to do FIRST=$(( $6 + 1 )) – giannis christofakis Aug 11 '15 at 11:58
14

First of all there can not be any space around = in variable declaration in bash.

To get what you want you can use eval.

For example a sample script like yours :

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    eval "$name"="'$(( $i + 1 ))q;d'"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

Prints :

1q;d
2q;d
3q;d
4q;d
5q;d

Use eval cautiously, some people call it evil for some valid reason.

declare would work too :

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    declare "$name"="$(( $i + 1 ))q;d"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done

also prints :

1q;d
2q;d
3q;d
4q;d
5q;d
  • What is the ! exclamation mark printf '%s\n' "${!name}" for? – giannis christofakis Aug 11 '15 at 12:24
  • 1
    Its called indirect expansion of bash parameter expansion..read this – heemayl Aug 11 '15 at 12:27
  • 1
    Bash also has a nicer alternative to declare / eval: printf -v varname '%fmt' args. Some bash-completion internal functions use this for call-by-reference. (pass the name of a variable to store into). – Peter Cordes Aug 11 '15 at 18:25
  • Note: Using declare only sets the variable in the local scope, while the eval approach sets it globally. – user Jun 27 at 3:21
9

If you want to reference a bash variable while having the name stored in another variable you can do it as follows:

$ var1=hello
$ var2=var1
$ echo ${!var2}
hello

You store the name of the variable you want to access in, say, var2 in this case. Then you access it with ${!<varable name>} where <variable name> is a variable holding the name of the variable you want to access.

  • There is portable way with eval var=\$$holder but eval is dangerous! – gavenkoa Aug 6 '18 at 22:01
1
index=0;                                                                                                                                                                                                           
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    name=$(($index + 1))
    echo "${name}q;d"
    index=$((index+1))
done

Is that what you are trying?

1

What I get from your code and your desired output (correct me if I'm wrong):
There is no use of the "FIRST"/"SECOND"/... variable names, you just need a loop with an index...

This will do the job:

for i in {1..5} ; do echo $i"q;d" ; done

  • Yes, you are right, except additionally I want to do an arithmetic function with a variable. – giannis christofakis Aug 11 '15 at 11:55
  • Can you give an example of this arithmetic function? Do you need the variable name (like "THIRD") for it or just the index value? – csny Aug 11 '15 at 12:01
  • SUM=$(($6 + $i)); echo $SUM"q;d", I see what I was doing wrong. – giannis christofakis Aug 11 '15 at 12:09

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.