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.