Bir değişkenin içeriğinin içeriğini kabuk betiği ile yazdırmak mümkün müdür? (dolaylı referans)


13

Aşağıdaki değişkenleri beyan ettiğimi varsayalım:

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

İçeriğini yazdırırsam aşağıdakileri görürüm:

$ echo $var
$test

$ echo $test
my string

İçeriğinin içeriğini yazdırmanın bir yolunu bulmak istiyorum $var(ki içeriği $test). Bu yüzden aşağıdakileri yapmaya çalıştım:

$ echo $(echo $var)
$test

Ama işte sonuç, $testdeğil "my string"... Değişkenlerin içeriğinin bash kullanarak yazdırılması mümkün mü?


Hangi kabuğu kullandığınızı veya hangi taşınabilirlik gereksinimleriniz olduğunu söylemek için yayınınızı düzenleyebilir misiniz ?
Michael Homer

@MichaelHomer Elbette, ancak bu bilgileri tam olarak nasıl kontrol edebilirim?
Rafael Muynarsk

Kontrol etmek için seçtiğin bir şey değil. Örneğin, komut dosyalarınızı ash, veya bash, veya csh, veya dash, ... veya zshveya POSIX ile mi çalıştırıyorsunuz , yoksa shfarklı sistemlerde mi çalışmanız gerekiyor?
Michael Homer

@MichaelHomer Ah, anlıyorum ... Ben bash kullanıyorum. Son soruyu değiştirip yeni bir etiket ekleyeceğim.
Rafael Muynarsk

Yanıtlar:


21

Bunu bash'ın dolaylı değişken genişlemesini kullanarak yapabilirsiniz ( $referans değişkeninizden dışarıda bırakmanız uygun olduğu sürece ):

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

3.5.3 Kabuk Parametresinin Genişletilmesi


10

varİçinde bulunan değişken adının ön ekinin bulunduğu durumda $aşağıdakileri kullanabilirsiniz eval:

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

Burada ne olur:

  • bash bir komut üreterek $vardeğere genişler ;$testeval echo $test
  • evalecho $testifadeyi değerlendirir ve istenen bir sonucu üretir.

Not kullanarak o evalgenel olarak (depolanır şeye bağlı olarak tehlikeli olabilir var), bu yüzden kaçınarak tercih ederim. Dolaylı genişletme özelliği durumunuz için daha iyidir (ancak $oturum açmanızdan kurtulmanız gerekir $test).


Tabii, bu bir yanlış. Orijinal yayında tek tırnak bulunur. Sabit.
Danila Kiver

4
Ben her zaman çift tırnak değişken referanslar (beklenmedik kelime bölme ve joker karakter genişletme sorun önlemek için) öneririm. İle eval, çift tırnak iki kat ihtiyaç bu hat: eval echo "\"$var\"". Dikkat edin, bu, evalbahsettiğiniz diğer kullanım tehlikeleri hakkında hiçbir şey yapmaz .
Gordon Davisson

9

Jesse_b'nin cevabına benzer , ancak değişken dolaylama yerine bir ad referans değişkeni kullanma ( 4.3+ gerektirir bash):

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

Name referans değişkeni var, başvurduğu değişkenin adını tutar. Değişken olarak kaydı kaldırıldığında $var, diğer değişkenin değeri döndürülür.

bash isim referanslarını özyinelemeli olarak çözer:

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

bashTamlık için, ilişkilendirilebilir bir dizi ( 4.0+) kullanmak, gereksinimlere bağlı olarak bunu çözmenin bir yoludur:

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

Bu, dinamik olarak belirlenebilen bir anahtar veya adla birden fazla değere erişmenin daha esnek bir yolunu sunar. Bu, belirli bir kategorinin tüm değerlerini tek bir dizide toplamak, ancak bunlara yine de kirletmediği için bazı anahtarlarla (örn. Kimlikle erişilebilen adlar veya amaçlara erişilebilen yol adları vb.) Erişmek istiyorsanız tercih edilebilir. betiğin değişken ad alanı.


3

İle zsh:

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

Bourne benzeri bir kabukla

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

Bu kabuklarda split + glob'u ( zshistisna olarak) önlemek için değişken genişletmelerin belirtilmesi gerektiğini ve echorastgele veriler için kullanılamayacağını unutmayın.

Her ikisi ile birlikte (e)ve evalkabuk kodu değerlendirmesi olduğundan, $varkeyfi bir komut enjeksiyon güvenlik açığı ( ${!var}yaklaşımlarla aynı ) olabileceği gibi kontrolünüzde kalmanız önemlidir .

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.