$ {! FOO} ve zsh


13

${!FOO}içinde bir çift yerine koyma gerçekleştirir bash, yani FOO'nun (string) değerini alır ve değişken adı olarak kullanır.
zshbu özelliği desteklemiyor.

Bu çalışmayı aynı şekilde yapmanın bir yolu var mı bashve zsh?

Arka fon:

Ortam değişkenlerinin bir listesi var.

PATH MAIL EDITOR

önce değişken adlarını sonra da değerlerini yazdırmak istersiniz.

Bu çalışıyor bashancak çalışmıyor zsh:

for VAR in LIST
do
        echo $VAR
        echo ${!VAR}
done

Bir şekilde “eski yol” ile mümkün olmalı eval, ama işe yarayamıyorum:

for VAR in LIST
do
        echo $VAR
        echo `eval \$$VAR`
done

Neden böyle ${${VAR}}veya ${${${VAR}}}gerektiğinde bile keyfi olarak derin ikameler yapamayacağımı asla anlamayacağım , bunun için bir açıklama da iyi olurdu.


1
HAH! Zsh'ın daha fazla özelliğe sahip olması gerektiğini düşündüm.
Ярослав Рахматуллин

4
Övünmeye gerek yok bash, gerçekten aynı işleve (ve çok daha fazlasına) sahip, sadece farklı bir desen kullanıyor, yani ${(p)FOO}.
Profpatsch

2
@ ЯрославРахматуллин, zsh (e)parametre genişletme bayrağı zsh-2.6-beta17 (Mayıs 1996), (P)bayrak 3.1.5-pws-7 (1999) 'da eklendi. bash ${!var}2.0'da (Aralık 1996).
Stéphane Chazelas

Yanıtlar:


18

Hem bash hem de zsh'nin dolaylı genişletme yapmanın bir yolu vardır, ancak farklı sözdizimi kullanırlar.

Kullanarak dolaylı genişleme yapmak yeterince kolaydır eval; bu tüm POSIX ve çoğu Bourne mermisinde çalışır. Değer, kabukta özel bir anlama sahip karakterler içeriyorsa, uygun şekilde alıntı yapmaya dikkat edin.

eval "value=\"\${$VAR}\""
echo "$VAR"
echo "$value"

${${VAR}}işe yaramaz çünkü herhangi bir kabuğun uyguladığı bir özellik değildir. Parantez içindeki şey, içermeyen sözdizimi kurallarına uymalıdır ${VAR}. (Zsh'de, bu sözdizimi desteklenir, ancak farklı bir şey yapar: yuvalanmış ikameler aynı değer üzerinde birbirini izleyen dönüşümler gerçekleştirir; bu değer üzerinde kimlik dönüşümünü iki kez gerçekleştirdiğinden buna ${${VAR}}eşdeğerdir $VAR.)


19

Profpatsch tarafından orijinal sorunun altındaki yorum, ${(p)FOO}dolaylı değişken referansının içeriğini çıktılamak için örnek verir . Bayrak yanlış veya yazım hatası, küçük P harfi değil büyük P harfi olmalıdır. Kullanın: ${(P)FOO}.

Aşağıdakiler istenen çıktıyı üretmelidir:

#! /bin/zsh
LIST=(PATH MAIL EDITOR)
for VAR in ${LIST}
do
    print "${VAR}:  ${(P)VAR}"
done

Gönderen zshexpn adam sayfasında; bölümü - Parametre Genişleme Bayrakları :

P

  This forces the value of the parameter name to be interpreted as a further
  parameter name,  whose  value  will  be used where appropriate.  Note that
  flags set with one of the typeset family of commands (in particular case
  transformations) are not applied to the value of name used in this fashion.

  If used with a nested parameter or command substitution, the result of that
  will be taken as a parameter  name  in the  same  way.   For  example,  if
  you  have  `foo=bar'  and `bar=baz', the strings ${(P)foo}, ${(P)${foo}}, and
  ${(P)$(echo bar)} will be expanded to `baz'

Bir keresinde neden ${${${VAR}}}beklediğiniz çıktıyı üretmediğini okudum , ancak şu anda bulamıyorum. Aşağıdaki gibi bir şey yapabilirsiniz:

first="second" ; second="third" ; third="fourth" ; fourth="fifth"
print ${(P)${(P)${(P)first}}}
fifth

3

Eval'i doğru kullanmıyorsunuz. Örnek değerinizde, önce bir "$" (örn., $ VALUE) olan $ VAR değeri komut olarak yürütülür. İstediğin bu değil. Adı başka bir değişkenten alınan bir değişkenin genişlemesini değerlendirmek istiyorsunuz.

$ for i in `echo PATH MAIL EDITOR`; 
    do eval moo="\${$i}" 
    echo $moo 
done
/usr/local/sbin:/usr/local/bin:/usr/sbin:/u (...)
/var/mail/root
nano

0

{ba,z}sh çözüm

Hem {ba, z} sh hem de çalışan bir işlev. POSIX uyumlu olduğuna inanıyorum.

Verildiğinde uyarır:

  • Boş giriş
  • Birden fazla argüman
  • Ayarlanmamış bir değişken adı

# Expand the variable named by $1 into its value. Works in both {ba,z}sh
# eg: a=HOME $(var_expand $a) == /home/me
var_expand() {
  if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
    printf 'var_expand: expected one non-empty argument\n' >&2;
    return 1;
  fi
  eval printf '%s' "\"\${$1?}\""
}

POSIX'te functionne var ne de . [[...]]sh
Stéphane Chazelas

Bağımsız değişken olup olmadığının kontrolü, [ "$#" -eq 0 ](veya muhtemelen [ "$#" -ne 1 ]yalnızca bir bağımsız değişken beklediğiniz gibi) olmalıdır.
Stéphane Chazelas

@ StéphaneChazelas Teşekkürler, güncellendi. POSIX uyumluluğu için bir referans kabuk var mı? Ben de shell-checkyardımcı olabileceğini düşünüyorum .
Tom Hale

@ StéphaneChazelas Tekrar test, ben de tek bir boş argüman verildiğinde başarısız olmak istiyorum. 2. önerinizi ekledim. Şerefe!
Tom Hale

${1-}Verilen a='"" -o -n 1' [ -z $a ]alıntıya katılıyorum == 0. Ama $#her zaman tek bir jeton olmayacak mı?
Tom Hale
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.