Czy można wydrukować zawartość zmiennej za pomocą skryptu powłoki? (odniesienia pośrednie)


13

Załóżmy, że zadeklarowałem następujące zmienne:

$ var='$test'
$ test="my string"

Jeśli wydrukuję ich zawartość, zobaczę:

$ echo $var
$test

$ echo $test
my string

Chciałbym znaleźć sposób na wydrukowanie zawartości treści $var(która jest zawartością $test). Próbowałem więc wykonać następujące czynności:

$ echo $(echo $var)
$test

Ale tutaj wynik jest $testi nie "my string"... Czy można wydrukować zawartość zmiennych za pomocą bash?


Czy możesz edytować swój post, aby powiedzieć, z której powłoki korzystasz lub jakie masz wymagania dotyczące przenoszenia?
Michael Homer

@MichaelHomer Pewnie, ale jak dokładnie mogę sprawdzić te informacje?
Rafael Muynarsk

To bardziej coś, co wybierzesz niż coś do sprawdzenia. Na przykład, czy uruchamiasz swoje skrypty z ash, lub bash, lub csh, lub dash, ... zsh, lub POSIX sh, czy potrzebujesz pracy w różnych systemach?
Michael Homer

@MichaelHomer Ah, rozumiem ... Używam bash. Po prostu zmienię ostatnie pytanie i wstawię nowy tag.
Rafael Muynarsk

Odpowiedzi:


21

Możesz to zrobić za pomocą pośredniego rozszerzenia zmiennych bash (pod warunkiem, że możesz pominąć $zmienną referencyjną):

$ var=test
$ test="my string"
$ echo "$var"
test
$ echo "${!var}"
my string

3.5.3 Rozszerzenie parametru powłoki


10

W przypadku, gdy nazwa zmiennej zawarta varjest w prefiksie $, możesz użyć eval:

$ var='$test'
$ test="my string"
$ eval echo $var
my string

Co się tutaj stało:

  • bash rozwija $varsię do wartości $test, tworząc eval echo $testpolecenie;
  • evalocenia echo $testwyrażenie i daje pożądany wynik.

Pamiętaj, że używanie evalogólnie może być niebezpieczne (w zależności od tego, co jest przechowywane var), więc wolisz go unikać. Funkcja rozszerzenia pośredniego jest lepsza w twoim przypadku (ale musisz pozbyć się $logowania $test).


Jasne, to błąd. Oryginalny post zawiera pojedyncze cytaty. Naprawiony.
Danila Kiver

4
Zawsze polecam podwójne cytowanie odwołań do zmiennych (aby uniknąć kłopotów z nieoczekiwanym dzieleniem słów i rozwijaniem symboli zastępczych). Dzięki eval, trzeba dwóch warstw podwójnych cudzysłowach, linia to: eval echo "\"$var\"". Pamiętaj, że to nie ma wpływu na inne niebezpieczeństwa związane z używaniem eval, o których wspomniałeś.
Gordon Davisson

9

Podobne do odpowiedzi Jesse_b , ale przy użyciu zmiennej odwołania do nazwy zamiast pośredniej zmiennej (wymaga wersji bash4.3+):

$ declare -n var=test
$ test="my string"
$ echo "$var"
my string

Zmienna odwołania vardo nazwy zawiera nazwę zmiennej, do której się odwołuje. Gdy zmienna zostanie odwołana jako $var, zwracana jest wartość tej innej zmiennej.

bash rozwiązuje rekurencyjne odwołania do nazw:

$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world

Aby uzyskać kompletność, użycie tablicy asocjacyjnej (w wersji bash4.0+) jest również jednym ze sposobów rozwiązania tego problemu, w zależności od wymagań:

$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string

Zapewnia to bardziej elastyczny sposób uzyskiwania dostępu do więcej niż jednej wartości za pomocą klucza lub nazwy, które mogą być określane dynamicznie. Może to być preferowane, jeśli chcesz zebrać wszystkie wartości określonej kategorii w jednej tablicy, ale nadal możesz uzyskać do nich dostęp za pomocą jakiegoś klucza (np. Nazw dostępnych według identyfikatora lub ścieżek dostępnych według celu itp.), Ponieważ nie zanieczyszcza zmienna przestrzeń nazw skryptu.


3

Z zsh:

$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*

Z każdą powłoką podobną do Bourne'a

$ eval 'printf "%s\n" "'"$var"'"'
*

Pamiętaj, że w tych powłokach zmienne rozszerzenia muszą być cytowane, aby zapobiec split + glob ( zshbędącym wyjątkiem) i echonie mogą być używane do dowolnych danych.

Ponieważ zarówno (e)i evaljest powłoka ocena kod, ważne treść $varutrzymać się w granicach kontroli, jak w inny sposób, który może być dowolną usterkę wtrysku poleceń (sam z ${!var}podejść).

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.