Definir variables con un nombre de variable.

11

¿Qué hay de malo con este script? Estoy tratando de definir A1 = 1, B1 = 1, C1 = 1

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

y el resultado es:

./x.: line 7: A1=1: command not found
./x.: line 7: B1=1: command not found
./x.: line 7: C1=1: command not found
Ake Blomberg
fuente
1
No creo que puedas crear variables en bash como esta. Para esto están las matrices.
Jakuje
3
Uso eval "$x"1=1. Aunque, como señaló Jakuje, las matrices probablemente sean más adecuadas para este caso.
Andrea Corbellini
@AndreaCorbellini Deberías escribir eso como respuesta.
Sparhawk

Respuestas:

21

Una asignación de variable tiene la forma de un nombre de variable, seguido del signo igual, seguido del valor (opcional).

Esta es una tarea válida:

ABC=123

"$x"1=1no es una asignación válida, porque "$x"1no es un nombre de variable. Puede ser eval uated a un nombre de variable, pero no lo es. El caparazón, de hecho, cree que es un comando.

Una forma de hacer lo que quieres lograr es esta:

eval "$x"1=1

Otra forma en bash (pero no en otros shells) es:

declare "$x"1=1

O también (de nuevo bash-only):

let "$x"1=1

(No hay mucha diferencia en su caso).

Pero, como señaló Jakuje en los comentarios , es probable que desee ir con matrices, si su shell las tiene (ksh, bash o zsh).


Por completitud:

  • evalejecuta comandos arbitrarios. Entonces, si en el lado derecho del signo igual tiene una variable que se expande a algún comando, ese comando se ejecutará. El siguiente código:

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

    es equivalente a a=hello.

  • declarees un bash incorporado para asignar variables y no ejecutará ningún comando. El siguiente código:

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

    es equivalente a a='$(echo hello)'.

  • letes similar a declareque no ejecuta comandos. Pero al contrario de declare, letpuede usarse para operaciones aritméticas:

    let a="1 + 2"

    es equivalente a a=3.

Andrea Corbellini
fuente
Even ABC = 123es inválido. Porque se agrega espacio antes y después de la equal(=)señal.
Mahendran Sakkarai
3

Las preguntas frecuentes de bash tienen una entrada sobre indirección. En la mayoría de los casos de uso, lo que debería hacer es usar una matriz asociativa o indexada. También puedes usar

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
}

Consulte la entrada de Preguntas frecuentes para obtener más opciones para hacer esto y evitar las citas desordenadas eval.

Peter Cordes
fuente
0

Puedes usar código como el siguiente. En su shell de código se ejecuta "$x"1=1como un comando porque no es una asignación de variable válida.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done
AVJ
fuente
¿Qué caparazón estás usando? Usando bosh bash 4.1.7 y 4.3.11 obtengo errores command not found <varname>=1cuando intento hacer eso (obviamente con <varname> es el valor que almacené a)
Eric Renouf
según lo explicado por @Andrea Corbellini, tenemos que usar let, declare o eval para asignar valor ...
AVJ
1
No necesitas echoaquí! Justo a="$x"1. También letes un contexto aritmético, por lo que solo puede asignar números con él.
Peter Cordes
declare $a=foobartrabajos.
Peter Cordes