11

What's wrong with this script? I'm trying to define A1=1, B1=1, C1=1

LIST="A B C"
for x in $LIST
do
    "$x"1=1
done

and the result is:

./x.: line 7: A1=1: command not found
./x.: line 7: B1=1: command not found
./x.: line 7: C1=1: command not found
  • 1
    I don't think you can create variables in bash like this. This is what are the arrays for. – Jakuje Aug 22 '15 at 12:30
  • 3
    Use eval "$x"1=1. Although, as Jakuje noted, arrays are probably better suited for this case. – Andrea Corbellini Aug 22 '15 at 12:38
  • @AndreaCorbellini You should write that as an answer. – Sparhawk Aug 22 '15 at 12:43
21

A variable assignment has the form of a variable name, followed by the equal sign, followed by the (optional) value.

This is a valid assignment:

ABC=123

"$x"1=1 is not a valid assignment, because "$x"1 is not a variable name. It may be evaluated to a variable name, but it isn't. The shell, in fact, believes it is a command.

One way for doing what you want to achieve is this:

eval "$x"1=1

Another way in bash (but not in other shells) is:

declare "$x"1=1

Or also (again bash-only):

let "$x"1=1

(There is no much difference in your case.)

But, as Jakuje noted in the comments, you probably want to go with arrays, if your shell has them (ksh, bash or zsh).


For completeness:

  • eval executes arbitrary commands. So, if on the right side of the equal sign you have a variable that expands to some command, that command will be executed. The following code:

    x=a
    y='$(echo hello)'
    eval "$x=$y"
    

    is equivalent to a=hello.

  • declare is a bash builtin to assign variables and won't execute any command. The following code:

    x=a
    y='$(echo hello)'
    declare "$x=$y"
    

    is equivalent to a='$(echo hello)'.

  • let is similar to declare, in that it doesn't execute commands. But contrary to declare, let may be used for arithmetic operations:

    let a="1 + 2"
    

    is equivalent to a=3.

  • Even ABC = 123 is invalid. Because space is added before and after the equal(=) sign. – Mahendran Sakkarai Nov 6 at 6:10
3

The bash FAQ has an entry on indirection. In most use-cases, what you should actually do is use an associative or indexed array. You can also use

func_call_by_reference() { # Bash 4.3
    typeset -n ref=$1   # nameref to the variable named by the caller
    ref=( "val1" "val2" ... )  # return an array by reference
}

See that FAQ entry for more options for doing this while still avoiding messy eval quoting.

0

You can use code like following. In your code shell executes "$x"1=1 as a command because it not a valid variable assignment.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done
  • What shell are you using? Using bosh bash 4.1.7 and 4.3.11 I get errors about command not found <varname>=1 when I try to do that (obviously with <varname> being the value I stored in a) – Eric Renouf Aug 22 '15 at 13:52
  • as explained by @Andrea Corbellini , we have to use let, declare or eval to assign value.. – AVJ Aug 22 '15 at 14:21
  • 1
    you don't need echo here! Just a="$x"1. Also let is an arithmetic context, so you can only assign numbers with it. – Peter Cordes Aug 23 '15 at 3:06
  • declare $a=foobar works. – Peter Cordes Aug 23 '15 at 3:11

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.