Zdefiniuj zmienne o nazwie zmiennej

11

Co jest nie tak z tym skryptem? Próbuję zdefiniować A1 = 1, B1 = 1, C1 = 1

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

a wynikiem jest:

./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
źródło
1
Nie sądzę, że można tworzyć zmienne w bash tak jak to. Po to są tablice.
Jakuje,
3
Zastosowanie eval "$x"1=1. Chociaż, jak zauważył Jakuje, tablice prawdopodobnie lepiej pasują do tego przypadku.
Andrea Corbellini,
@AndreaCorbellini Powinieneś napisać to jako odpowiedź.
Sparhawk

Odpowiedzi:

21

Przypisanie zmiennej ma postać nazwy zmiennej, po której następuje znak równości, po której następuje (opcjonalnie) wartość.

To jest prawidłowe zadanie:

ABC=123

"$x"1=1nie jest poprawnym przypisaniem, ponieważ "$x"1nie jest nazwą zmiennej. To może być eval uated do nazwy zmiennej, ale tak nie jest. W rzeczywistości powłoka uważa, że ​​jest to polecenie.

Jednym ze sposobów robienia tego, co chcesz osiągnąć, jest:

eval "$x"1=1

Innym sposobem na bash (ale nie w innych powłokach) jest:

declare "$x"1=1

Lub też (ponownie tylko bash):

let "$x"1=1

(W twoim przypadku nie ma dużej różnicy).

Ale, jak zauważył Jakuje w komentarzach , prawdopodobnie będziesz chciał korzystać z tablic, jeśli twoja powłoka je ma (ksh, bash lub zsh).


Dla pełności:

  • evalwykonuje dowolne polecenia. Tak więc, jeśli po prawej stronie znaku równości masz zmienną, która rozwija się do jakiegoś polecenia, to polecenie zostanie wykonane. Poniższy kod:

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

    jest równoważne z a=hello.

  • declareto wbudowane bash do przypisywania zmiennych i nie wykonuje żadnych poleceń. Poniższy kod:

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

    jest równoważne z a='$(echo hello)'.

  • letjest podobny do tego declare, że nie wykonuje poleceń. Ale w przeciwieństwie do declare, letmoże być stosowany do operacji arytmetycznych:

    let a="1 + 2"

    jest równoważne z a=3.

Andrea Corbellini
źródło
Nawet ABC = 123jest nieprawidłowy. Ponieważ spacja jest dodawana przed equal(=)znakiem i po nim .
Mahendran Sakkarai
3

FAQ bash zawiera wpis dotyczący pośrednictwa. W większości przypadków użycia należy właściwie zastosować tablicę asocjacyjną lub indeksowaną. Możesz także użyć

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
}

Zapoznaj się z wpisem FAQ, aby uzyskać więcej opcji, a jednocześnie unikaj niepotrzebnych evalcytatów.

Peter Cordes
źródło
0

Możesz użyć kodu w następujący sposób. W twoim kodzie powłoka jest wykonywana "$x"1=1jako polecenie, ponieważ nie jest to prawidłowe przypisanie zmiennej.

LIST="A B C"
for x in $LIST
do
    a=$(echo "$x"1)
    let $a=1
done
AV J
źródło
Jakiej powłoki używasz? Używając bosh bash 4.1.7 i 4.3.11, dostaję błędy, command not found <varname>=1gdy próbuję to zrobić (oczywiście z <nazwa> jest wartością, w której zapisałem a)
Eric Renouf
jak wyjaśniono @Andrea Corbellini, musimy użyć let, deklarować lub eval, aby przypisać wartość ..
AVJ
1
nie potrzebujesz echotutaj! Właśnie a="$x"1. Również letjest arytmetyka kontekst, dzięki czemu można przypisać tylko numery z nim.
Peter Cordes,
declare $a=foobarPracuje.
Peter Cordes,