Değişken adı dize olarak depolanırsa değişken değeri nasıl alınır?


142

Değişken adını dize olarak alırsam bir bash değişken değerini nasıl alabilirim?

var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.

Bağlam:

Bazı AMI'lerim ( Amazon Machine Image ) var ve her bir AMI'den birkaç örnek vermek istiyorum. Önyüklemeyi bitirir bitirmez, her örneği AMI türüne göre ayarlamak istiyorum. Herhangi bir AMI içinde çok sayıda komut dosyası veya gizli anahtar yapmak istemiyorum, bu yüzden genelleştirilmiş bir başlangıç ​​komut dosyası hazırladım ve S3'e halka açık bir bağlantıyla koydum . Rc.local'da, başlangıç ​​komut dosyasını getiren ve yürüten küçük bir kod parçası koydum. AMI'lerde sahip olduğum tek şey bu. Daha sonra her AMI, tüm AMI'ler ve her biri için özel kurulum komut dosyaları için geçerli olan ortak bir yapılandırma komut dosyasına erişir. Bu komut dosyaları özeldir ve erişmek için imzalı bir URL gerekir.

Şimdi, bir AMI (my_private_ami_1) örneğini tetiklediğimde, anahtar / değer çifti açısından tüm özel komut dosyaları için imzalı URL içeren S3'te sunulan bir dosya için imzalı bir URL geçiriyorum.

config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
Başlangıç ​​betiği çalıştığında, yukarıdaki dosyayı indirir ve indirir source. Ardından AMI türünü kontrol eder ve kendisi için doğru kurulum komut dosyasını seçer.

ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises

Şimdi AMI türlerine bakılmaksızın örnekleri tetikleyebilen genel bir koda sahip olabilirim ve örnekler kendileriyle ilgilenebilir.

Yanıtlar:


257

Şunları kullanabilirsiniz ${!a}:

var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'

Bu dolaylı parametre genişlemesine bir örnektir :

Parametre genişletmenin temel şekli ${parameter}. Değeri parameterikame edilir.

Eğer ilk karakteri parameterbir ünlem işareti (!) İse, değişken bir dolaylılık düzeyi sunar. Bash, değişkenin parameteradı olarak geri kalanından oluşan değişkenin değerini kullanır ; bu değişken daha sonra genişletilir ve bu değer ikame değerinin parameterkendisinden ziyade geri kalanında kullanılır .


4
Bu OSX bash benim için çalışıyor, ama debian değil mi? Debian'da Bad substitutionhata alıyorum.
ev

11
@ 23inhouse Senaryonuzu kullanarak /bin/shmı çalıştırıyorsunuz ? Öyleyse, /bin/bashbunun yerine kullanmayı deneyin . Debian Squeeze'den itibaren bunun yerine/bin/sh bir sembolik bağlantıdashbash olarak değiştirildi . dashbu sözdizimini desteklemez ve bir Bad substitutionhata verir.
Phil Ross

8
Bir diziye ait değişken adı için bu çalışmanın bir yolu var mı?
Loupax

Ubuntu üzerinde bash ile çalışır
Sergey P. aka azure

1
@DoronShai Bu, gnu.org/software/bash/manual/html_node/… adresindeki Bash Referans Kılavuzu'nda belgelenen dolaylı parametre genişletme örneğidir
Phil Ross

29
X=foo
Y=X
eval "Z=\$$Y"

Z'yi "foo" olarak ayarlar

Kullanmaya dikkat edin, evalçünkü bu, aşağıdaki değerlerle kodun kazayla hariç tutulmasına izin verebilir${Y} . Bu, kod enjeksiyonu yoluyla zarar verebilir.

Örneğin

Y="\`touch /tmp/eval-is-evil\`"

oluşturur /tmp/eval-is-evil. Bu rm -rf /elbette bazıları da olabilir .


kuyruğumu kurtardım, ty
rafya

9

Arama anahtar kelimelerimi değiştirdim ve Anladım :).

eval a=\$$a
Zaman ayırdığınız için teşekkürler.


Eval'i kullanarak dikkatli olun, çünkü bu, içindeki değerler yoluyla kodun yanlışlıkla hariç tutulmasına izin verebilir ${Y}. Kullanıcı "anon" cevabında benim ek bakın.
try-catch-nihayet

Bu tek çalışan cevaptır. Kendi ironik olduğunu!
Ctrl S

8

Diğer zsh kullanıcılarım için, kabul edilen cevapla aynı şeyi yapmanın yolu kullanmaktır:

${(P)a}

Buna Parametre adının değiştirilmesi denir

Bu, parametre adının değerini, uygun olan yerde kullanılacak başka bir parametre adı olarak yorumlanmaya zorlar. Komut dizisi ailesinden (özellikle de dönüşümler) biriyle ayarlanan bayrakların bu şekilde kullanılan adın değerine uygulanmadığını unutmayın.

Yuvalanmış bir parametre veya komut ikamesi ile birlikte kullanılırsa, bunun sonucu aynı şekilde parametre adı olarak alınır. Örneğin, 'foo = bar' ve 'bar = baz' varsa, $ {(P) foo}, $ {(P) $ {foo}} ve $ {(P) $ (eko çubuğu) dizeleri } 'baz' değerine genişletilecek.

Benzer şekilde, başvurunun kendisi iç içe yerleştirilmişse, bayrağa sahip ifade doğrudan parametre adıyla değiştirilmiş gibi ele alınır. Bu iç içe geçmiş ikame birden fazla sözcük içeren bir dizi üretirse bir hatadır. Örneğin, assoc parametresinin ilişkilendirilebilir bir dizi olduğu 'name = assoc' ise, '$ {$ {(P) name} [elt]}' ilişkilendirilmiş 'elt' aboneliğine ait öğeyi ifade eder.


0

modern mermiler zaten dizileri (ve hatta ilişkisel dizileri) destekliyor. Bu yüzden lütfen onları kullanın ve daha az eval kullanın.

var1="this is the real value"
array=("$var1")
# or array[0]="$var1"

sonra aramak istediğinizde, echo $ {array [0]}


Eğer komut satırı argümanından (örneğin as $1) dize alırsam bu işe yarar ?
jena

0

Cevaba dayanarak: https://unix.stackexchange.com/a/111627

###############################################################################
# Summary: Returns the value of a variable given it's name as a string.
# Required Positional Argument: 
#   variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
get_value_of()
{
    variable_name=$1
    variable_value=""
    if set | grep -q "^$variable_name="; then
        eval variable_value="\$$variable_name"
    fi
    echo "$variable_value"
}

test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")

0

Dizilerle aynı sorunu yaşadım, dizileri de manipüle ediyorsanız, bunu nasıl yapacağınız aşağıda açıklanmıştır:

array_name="ARRAY_NAME"
ARRAY_NAME=("Val0" "Val1" "Val2")

ARRAY=$array_name[@]
echo "ARRAY=${ARRAY}"
ARRAY=("${!ARRAY}")
echo "ARRAY=${ARRAY[@]}"
echo "ARRAY[0]=${ARRAY[0]}"
echo "ARRAY[1]=${ARRAY[1]}"
echo "ARRAY[2]=${ARRAY[2]}"

Bu çıktı:

ARRAY=ARRAY_NAME[@]
ARRAY=Val0 Val1 Val2
ARRAY[0]=Val0
ARRAY[1]=Val1
ARRAY[2]=Val2
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.