bash dynamiczne (zmienne) nazwy zmiennych


12

Chcę dynamicznie tworzyć sekwencję ciągów, manipulując tablicą elementów i tworząc procedurę arytmetyczną.

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

Wynik pożądania byłby poniżej dla $6równości 0.

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

Ale dostaję ten błąd

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

Myślę, że to coś prostego. Kiedyś coś działało

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"

1
Czy możesz to trochę lepiej wyjaśnić. Naprawdę nie rozumiem, co próbujesz zrobić.
neuron

Co powinno zrobić `$ name = $ ((6 $ + 1))`?
PSkocik,

@PSkocik Miałem nadziejęFIRST=$(( $6 + 1 ))
giannis christofakis,

Odpowiedzi:


16

Przede wszystkim nie może być żadnej przestrzeni =w deklaracji zmiennej w bash.

Aby uzyskać to, czego chcesz, możesz użyć eval.

Na przykład przykładowy skrypt jak twój:

#!/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

Wydruki:

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

Używaj evalostrożnie, niektórzy nazywają to złem z jakiegoś ważnego powodu.

declare też by działał:

#!/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

drukuje również:

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

Do czego służy !wykrzyknik printf '%s\n' "${!name}"?
giannis christofakis,

1
Nazywa się to pośrednim rozszerzaniem rozszerzania bashparametrów.
Przeczytaj

1
Bash ma również alternatywę ładniejszy declare/ eval: printf -v varname '%fmt' args. Niektóre funkcje wewnętrzne kończące bash używają tego do wywołania przez referencję. (przekaż nazwę zmiennej, w której chcesz zapisać).
Peter Cordes,

Uwaga: Użycie declaretylko ustawia zmienną w zasięgu lokalnym, podczas gdy evalpodejście ustawia ją globalnie.
użytkownik

11

Jeśli chcesz odwoływać się do zmiennej bash, zachowując nazwę w innej zmiennej, możesz to zrobić w następujący sposób:

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

W tym przypadku przechowujesz nazwę zmiennej, do której chcesz uzyskać dostęp, powiedzmy var2. Następnie uzyskujesz do niego dostęp, ${!<varable name>}gdzie <variable name>jest zmienna zawierająca nazwę zmiennej, do której chcesz uzyskać dostęp.


Jest przenośny sposób, eval var=\$$holderale evaljest niebezpieczny!
gavenkoa,

1
index=0;                                                                                                                                                                                                           
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    name=$(($index + 1))
    echo "${name}q;d"
    index=$((index+1))
done

Czy tego właśnie próbujesz?


1

Co otrzymuję z twojego kodu i pożądanych danych wyjściowych (popraw mnie, jeśli się mylę):
Nie używa się nazw zmiennych „FIRST” / „SECOND” / ..., wystarczy pętla z indeksem. .

Spowoduje to wykonanie zadania:

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


Tak, masz rację, tyle że dodatkowo chcę wykonać funkcję arytmetyczną ze zmienną.
giannis christofakis,

Czy możesz podać przykład tej funkcji arytmetycznej? Czy potrzebujesz do tego nazwy zmiennej (np. „TRZECIA”), czy tylko wartości indeksu?
cny

SUM=$(($6 + $i)); echo $SUM"q;d", Widzę, co robiłem źle.
giannis christofakis,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.