Definieren Sie Variablen mit einem Variablennamen

11

Was ist los mit diesem Skript? Ich versuche A1 = 1, B1 = 1, C1 = 1 zu definieren

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

und das Ergebnis ist:

./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
quelle
1
Ich glaube nicht, dass Sie solche Variablen in Bash erstellen können. Dafür sind die Arrays da.
Jakuje
3
Verwenden Sie eval "$x"1=1. Obwohl, wie Jakuje bemerkte, Arrays wahrscheinlich besser für diesen Fall geeignet sind.
Andrea Corbellini
@AndreaCorbellini Das solltest du als Antwort schreiben.
Sparhawk

Antworten:

21

Eine Variablenzuweisung hat die Form eines Variablennamens, gefolgt vom Gleichheitszeichen, gefolgt vom (optionalen) Wert.

Dies ist eine gültige Zuordnung:

ABC=123

"$x"1=1ist keine gültige Zuordnung, da "$x"1es sich nicht um einen Variablennamen handelt. Es kann sein , eval uated zu einem Variablennamen, aber es ist nicht. Die Shell glaubt tatsächlich, dass es ein Befehl ist.

Eine Möglichkeit, das zu tun, was Sie erreichen möchten, ist folgende:

eval "$x"1=1

Ein anderer Weg in Bash (aber nicht in anderen Shells) ist:

declare "$x"1=1

Oder auch (wieder nur Bash):

let "$x"1=1

(In Ihrem Fall gibt es keinen großen Unterschied.)

Aber, wie Jakuje in den Kommentaren bemerkte , möchten Sie wahrscheinlich mit Arrays arbeiten, wenn Ihre Shell diese hat (ksh, bash oder zsh).


Zur Vollständigkeit:

  • evalführt beliebige Befehle aus. Wenn Sie also auf der rechten Seite des Gleichheitszeichens eine Variable haben, die zu einem Befehl erweitert wird, wird dieser Befehl ausgeführt. Der folgende Code:

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

    ist äquivalent zu a=hello.

  • declareist eine integrierte Bash zum Zuweisen von Variablen und führt keinen Befehl aus. Der folgende Code:

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

    ist äquivalent zu a='$(echo hello)'.

  • letist insofern ähnlich declare, als es keine Befehle ausführt. Aber im Gegensatz zu declare, letkann für arithmetische Operationen verwendet werden:

    let a="1 + 2"

    ist äquivalent zu a=3.

Andrea Corbellini
quelle
Auch ABC = 123ist ungültig. Weil vor und nach dem equal(=)Schild Platz hinzugefügt wird .
Mahendran Sakkarai
3

Die Bash-FAQ enthält einen Eintrag zur Indirektion. In den meisten Anwendungsfällen sollten Sie tatsächlich ein assoziatives oder indiziertes Array verwenden. Sie können auch verwenden

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
}

In diesem FAQ-Eintrag finden Sie weitere Optionen, während Sie dennoch unordentliche evalZitate vermeiden .

Peter Cordes
quelle
0

Sie können folgenden Code verwenden. In Ihrer Code-Shell wird "$x"1=1als Befehl ausgeführt, da es sich nicht um eine gültige Variablenzuweisung handelt.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done
AVJ
quelle
Welche Shell benutzt du? Mit bosh bash 4.1.7 und 4.3.11 bekomme ich Fehler, command not found <varname>=1wenn ich das versuche (offensichtlich mit <varname> als dem Wert, in dem ich gespeichert habe a)
Eric Renouf
Wie von @Andrea Corbellini erklärt, müssen wir let, declare oder eval verwenden, um einen Wert zuzuweisen.
AVJ
1
du brauchst echohier nicht! Einfach a="$x"1. Ist auch letein arithmetischer Kontext, so dass Sie ihm nur Zahlen zuweisen können.
Peter Cordes
declare $a=foobarfunktioniert.
Peter Cordes