${!FOO}
wykonuje podwójne podstawienie w bash
, co oznacza, że pobiera wartość (ciąg) FOO i używa jej jako nazwy zmiennej.
zsh
nie obsługuje tej funkcji.
Czy istnieje sposób, aby to działało tak samo w bash
i zsh
?
Tło:
Mam listę zmiennych środowiskowych, takich jak
PATH MAIL EDITOR
i chcą najpierw wydrukować nazwy zmiennych, a następnie ich wartości.
Działa to, bash
ale nie zsh
:
for VAR in LIST
do
echo $VAR
echo ${!VAR}
done
Powinno to być jakoś możliwe „po staremu” eval
, ale nie mogę zmusić go do działania:
for VAR in LIST
do
echo $VAR
echo `eval \$$VAR`
done
Nigdy nie zrozumiem, dlaczego nie mogę po prostu dokonywać dowolnych głębokich zmian, takich jak, ${${VAR}}
a nawet, ${${${VAR}}}
jeśli zajdzie taka potrzeba, więc wyjaśnienie tego również byłoby miłe.
bash
zsh
variable-substitution
for
Profpatsch
źródło
źródło
bash
, to rzeczywiście ma tę samą funkcję (i wiele więcej), używa tylko innego wzorca, a mianowicie${(p)FOO}
.(e)
flaga rozszerzenia parametru zsh została dodana w zsh-2.6-beta17 (maj 1996),(P)
flaga w 3.1.5-pws-7 (1999). bash's${!var}
w wersji 2.0 (grudzień 1996).Odpowiedzi:
Zarówno bash, jak i zsh mają sposób na wykonanie pośredniej rozbudowy, ale używają innej składni.
Łatwo jest przeprowadzić ekspansję pośrednią za pomocą
eval
; działa to we wszystkich POSIX-ach i większości powłok Bourne'a. Staraj się cytować poprawnie, jeśli wartość zawiera znaki, które mają specjalne znaczenie w powłoce.${${VAR}}
nie działa, ponieważ nie jest to funkcja implementowana przez żadną powłokę. Rzeczy w nawiasach klamrowych muszą być zgodne z regułami składni, które nie obejmują${VAR}
. (W zsh jest to obsługiwana składnia, ale robi coś innego: zagnieżdżone podstawienia wykonują kolejne transformacje na tej samej wartości;${${VAR}}
jest to równoważne,$VAR
ponieważ wykonuje to transformację tożsamości dwukrotnie na wartości).źródło
Komentarz pod pierwotnym pytaniem autorstwa Profpatscha podaje przykład
${(p)FOO}
do wyprowadzenia treści odwołania do zmiennej pośredniej. Flaga jest niepoprawna lub literówka, powinna być wielką literą P, a nie małą literą p. Zastosowanie:${(P)FOO}
.Poniższe powinny dać pożądany wynik:
Ze strony podręcznika zshexpn ; sekcja - Flagi rozszerzeń parametrów :
Kiedyś przeczytałem, dlaczego
${${${VAR}}}
nie daje oczekiwanych wyników, ale w tej chwili nie mogę ich znaleźć. Możesz zrobić coś takiego:źródło
Nie używasz eval poprawnie. W twoim przykładzie wartość $ VAR poprzedzona znakiem „$” (tj. „$ VALUE”) zostałaby wykonana jako polecenie. Nie tego chcesz. Chcesz ocenić rozszerzenie zmiennej, której nazwa pochodzi od innej zmiennej.
źródło
{ba,z}sh
rozwiązanieOto funkcja, która działa zarówno w {ba, z} sh. Wierzę, że jest również zgodny z POSIX.
Ostrzega, gdy podano:
źródło
function
ani[[...]]
w POSIXsh
.[ "$#" -eq 0 ]
(lub prawdopodobnie,[ "$#" -ne 1 ]
ponieważ oczekujesz tylko jednego argumentu).shell-check
może pomóc.${1-}
podanoa='"" -o -n 1'
[ -z $a ]
==0
. Ale czy nie$#
zawsze będzie pojedynczy token?