Mogę to zrobić, ale wymaga to utworzenia ciągu zmiennej, a następnie wyrejestrowania go. Czy jest jakiś sposób, aby skrócić to do prostszego stwierdzenia?
#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"
for fruit in $( echo $FRUITS ); do
fruit_colour="${fruit}_COLOUR"
echo $fruit is ${!fruit_colour}
done
Próbowałem wiele rzeczy, jak ${!"${fruit}_COLOUR"}
i \$${fruit}_COLOUR
wielu innych wariantów, ale jedynym sposobem, który pracował jest za pomocą łańcucha.
!
Składnia jest flaga na zmiennej substytucji, że w zasadzie mówi „substytutem dwa razy”. Nie zmienia to wymogu, że to, co jest w środku,${…}
musi być nazwą zmiennej. Więc nie, nie możesz uniknąć używania zmiennej zawierającej nazwę, chyba że użyjesz innej metody (eval
).Odpowiedzi:
Po pierwsze, nie musisz używać
$(echo $FRUITS)
wfor
wyciągu. Wystarczy$FRUITS
użyć. Następnie możesz pozbyć się jednej z linii wewnątrz pętli, używająceval
.eval
Po prostu mówi bash, aby drugą ocenę z następującym stwierdzeniem (czyli o jeden więcej niż normalnej oceny).\$
Przetrwa pierwszej oceny, jak$
i następna ocena następnie traktuje to$
jako początek nazwy zmiennej, która postanawia „Yellow”, etc.W ten sposób nie musisz mieć osobnego kroku, który tworzy tymczasowy ciąg znaków (co moim zdaniem było głównym celem twojego pytania).
W przypadku metody alternatywnej, o której wspomniał Patrick w komentarzu (powyżej), można zamiast tego użyć tablicy asocjacyjnej , w której indeks elementu nie musi być liczbą całkowitą. Możesz użyć łańcucha, takiego jak nazwa rodzaju owocu. Oto przykład z wykorzystaniem tablicy asocjacyjnej bash:
źródło
Możesz użyć wbudowanego basha,
eval
aby to zrobić:Zwróć uwagę na znak odwróconego dolara. Zasadniczo, „eval” przyczyny linia
bash
do podstawniki, na$fruit
i${fruit_color}
, a następnie za pomocąeval
zrobić drugą rundę substition przed wywołaniemecho
.źródło
Nie potrzebujesz ewaluacji.
eval
jest wskazówką w większości języków, że robisz coś złego.źródło
eval
ponieważ przynajmniej ludzie wiedzą, że jest niebezpieczny,${!var}
jest tak samo niebezpieczny wbash
(również podatność na iniekcję poleceń, jeśli$chosen_prefix
jest pod kontrolą atakującego) i mniej osób jest tego świadomych. Spróbowaćvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. Najlepszym podejściem jest tutaj tablica asocjacyjna.