Bir ortam değişkenini komut satırına nasıl ayarlarım ve komutlarda görünmesini nasıl sağlarım?


Yanıtlar:


180

Bunun nedeni, kabuğun gerçekte komutu çalıştırmadan önce komut satırındaki değişkeni genişletmesidir ve o sırada değişken yoktur. Eğer kullanırsan

TEST=foo; echo $TEST

Çalışacak.

exportdeğişkeni daha sonra yürütülen komutların ortamında görünmesini sağlar (bunun bash nasıl göründüğü için help export). Yalnızca bir komutun ortamında görünmek için değişkene ihtiyacınız varsa, denediğinizi kullanın, örneğin:

TEST=foo your-application

1
Peki ya / usr / bin / env? Bu da işe yaramıyor, nedenini biliyor musun?
Benubird

5
Aynı sebep - kabuk $TEST, komut satırı çalıştırılmadan önce genişler . Çalıştığında echo(ayrıca echogenellikle kabuk yerleşik komutuna çevirip çevirmeyeceğine de dikkat edin /bin/echo) ortamında ayarlanan değişkeni görür. Bununla birlikte, değişken içeriğini ortamından çıkarmayı echo $TESTsöylemez . Kabuğa, şu anda denilen değişkende her ne olduğu ile tartışarak çalışmasını söyler - ve bunlar çok farklı şeylerdir. echoTESTechoTEST
peterph

@peterph Kabuk, komutu gerçekten çalıştırmadan önce komut satırındaki değişkeni genişletirse, neden onu genişletmiyor var=value sh -c 'echo "$var"'?
18'de

Size burada açıkladığım gibi : değişkenler çift tırnak içinde (örn. "… $var …") Genişlemiş, ancak tek tırnak içinde değil (örn '… $var …'.). echo "$var"Tek tırnak içinde olduğundan , dizenin tamamı sh -cdış, etkileşimli kabuk tarafından yorumlanmadan new ( ) kabuğuna iletilir . … (Devamı)
G-Man

(Devam ediyor)… Dün igal’in dediği gibi iki ayrıştırma turu var - igal’in sorunuzu yanlış anladığına inanıyorum. Ana kabuk tarafından yapılan ayrıştırma dışında iki ayrıştırma turu yoktur . İki ayrıştırma turu vardır - biri dış, etkileşimli (üst) kabuk, diğeri ise yeni ( sh -c) alt kabuk tarafından yapılır.
G-Man

39

Ortam değişkenlerinden ziyade, sınırlı bir kapsam için kabuk değişkenlerine sahip olmak istediğinizden şüpheleniyorum . Ortam değişkenleri, yürütüldüklerinde komutlara iletilen dizelerin bir listesidir .

İçinde

var=value echo whatever

var=valueDize yankının aldığı ortama geçiriyorsunuz . Ancak, echoçevre listesinde herhangi bir şey yapmaz ve yine de çoğu kabukta, echoyerleşiktir ve bu nedenle yürütülmez .

Yazmış olsaydın

var=value sh -c 'echo "$var"'

Bu başka bir konu olurdu. Burada, geçiriyorsanız var=valueiçin shkomuta ve shçevresini kullanmak oluyor. Kabuklar, çevrelerinden aldıkları değişkenlerin her birini kabuk değişkenine dönüştürür, böylece varortam değişkeni shbir $vardeğişkene dönüştürülür ve bu echokomut satırında genişlediğinde , olur echo value. Çevre miras varsayılan olarak olduğundan, echoayrıca alacak var=valueortamındaki (veya infaz edildi olsaydı), ama yine echoçevre umursamıyor.

Şimdi, şüphelendiğimde, istediğiniz şey kabuk değişkenlerinin kapsamını sınırlamaksa, birkaç olası yaklaşım vardır.

Taşınabilir (Bourne ve POSIX):

(var=value; echo "1: $var"); echo "2: $var"

Yukarıdaki (...) bir alt kabuk başlatır (çoğu kabukta yeni bir kabuk işlemi), bu nedenle orada bildirilen herhangi bir değişken yalnızca bu alt kabuğu etkileyecektir, bu nedenle yukarıdaki kodun "1: değer" vermesini beklerdim. ve "2:" veya "2: önceden belirlenmiş her neyse".

Bourne benzeri mermilerin çoğunda, işlevleri ve "yerel" yerleşimi kullanabilirsiniz:

f() {
  local var
  var=value
  echo "1: $var"
}
f
echo "2: $var"

Zsh ile satır içi işlevleri kullanabilirsiniz:

(){ local var=value; echo "1: $var"; }; echo "2: $var"

veya:

function { local var=value; echo "1: $var"; }; echo "2: $var"

Bash ve zsh ile (ancak kül, pdksh veya AT&T ksh ile değil), bu numara da işe yarıyor:

var=value eval 'echo "1: $var"'; echo "2: $var"

Birkaç kabuklarda çalışan bir varyant ( dash, mksh, yash), ancak zsh(içinde olmadıkça sh/ kshöykünme):

var=value command eval 'echo "1: $var"'; echo "2: $var"

( POSIX mermilerinde command(burada eval) özel bir yapının önünü kullanarak uzmanlıklarını kaldırır (burada bunlardan gelen değişken atamaları geri döndükten sonra etkin kalır)


Benim amaçlarıma göre, bu doğru bir çözümdür. 'Var' değişkeninin kabul edilen cevapta olduğu gibi çevreyi kirletmesini istemiyorum.
kronenpj 13:17

6

Doğru yapıyorsunuz, ancak bash sözdiziminin yanlış yorumlanması kolaydır: bunun env var getirmesine echo $TESTneden olduğunu echove TESTsonra yazdırdığını düşünebilirsiniz , değil. Verilen

export TEST=123

sonra

TEST=456 echo $TEST

aşağıdaki diziyi içerir:

  1. Kabuk tüm komut satırını ayrıştırır ve tüm değişken değişkenlerini çalıştırır, böylece komut satırı olur.

    TEST=456 echo 123
  2. Komuttan önce ayarlanan temp değişkenlerini yaratır, böylece mevcut değerini kaydeder TESTve 456 ile üzerine yazar; komut satırı şimdi

    echo 123
  3. Bu durumda 123'ü stdout'a basan kalan komutu çalıştırır (bu yüzden kalan shell komutu temp değerini bile kullanmaz TEST)

  4. Değerini geri yükler TEST

Değişken ikame gerektirmediğinden, yerine printenv kullanın:

>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>

+1 printenvKavramı test etmek / kanıtlamak için faydalı buldum (aksine bir senaryo gibi davranır echo)
Daryn

5

Bu çalışmayı aşağıdakileri kullanarak alabilirsiniz:

TEST=foo && echo $TEST

6
Bu durumda, TEST=fooayrı bir ifade olarak çalışıyor - sadece bağlamında ayarlanmadı echo.
codeforester,
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.