Neden $ RANDOM 'env' çıktısına dahil edilmiyor?


23

envBir kabuk komutu olduğunu biliyorum , mevcut ortam değişkenlerinin bir listesini yazdırmak için kullanılabilir. Ve anladığım kadarıyla, RANDOMaynı zamanda bir ortam değişkeni.

Öyleyse neden envLinux’a başladığımda bu çıktı içermiyor RANDOM?


4
envbir kabuk komutu değildir, çünkü genellikle kabuğun içine yerleştirilmez.
schily

@schily bash için btw declare -x, bir kabuk yerleşik bir eşdeğerdir.
wjandrea

Yanıtlar:


42

RANDOMbir ortam değişkeni değil. Bazı mermiler tarafından tutulan bir kabuk değişkenidir. Genellikle varsayılan olarak dışa aktarılmaz. Bu yüzden çıktısında görünmüyor env.

Bir zamanlar en azından kullanılan konduktan sonra, bu olur çıktısında göstermek set, hangi kendisi tarafından, listeler geçerli kabuk oturumunda kabuk değişkenleri (ve fonksiyonları) ve bunların değerleri. Bu davranış kabuğa bağlıdır ve pdkshOpenBSD'de kullanıldığında, RANDOMdaha setönce kullanılmasa bile listelenir .


Bu cevabın geri kalanı RANDOM, ihraç edildiğinde ne olabileceği ile ilgilidir (yani bir ortam değişkenine dönüşmüş).

Onu dışa aktarmak export RANDOM, onu bir ortam değişkeni yapacaktır ancak bir alt işlemdeki değeri "rasgele ama statik" olacağı için kullanımı ciddi şekilde sınırlı olacaktır (yani, değişmeyen bir rasgele sayı olacaktır). Tam davranış kabukları arasında değişir.

pdkshAşağıdaki örnekte OpenBSD kullanıyorum ve her awkçalıştırmada yeni bir rastgele değer elde ediyorum (ancak aynı durumda her zaman aynı değer awk). Kullanarak bash, tüm davetlerde tam olarak aynı rastgele değeri elde ederdim awk.

$ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }'
25444 25444

$ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }'
30906 30906

İçinde bash, dışa aktarılan değer , kabuktaki RANDOMkullanımdan bağımsız olarak statik kalır RANDOM(her bir kullanımın $RANDOMhala yeni bir değer vereceği).

Her referans Bunun nedeni kabuk değişkeni RANDOM içinde bashkabuk erişim iç kılan get_random()işlevi değişkeni yeni bir rastgele değer vermek için, ama kabuk güncelleme gelmez ortam değişkeni RANDOM . Bu, diğer dinamik gibi davranış benzerdir bashgibi değişkenler, LINENO, SECONDS, BASHPIDvs.

Ortam değişkeni güncellemek için RANDOMde bash, bunu kabuk değişkeninin değerini atamak zorunda kalacak RANDOM ve yeniden ihracat it:

export RANDOM="$RANDOM"

Bunun rasgele sayı üretecinin tekrar tohumlanmasında ek bir yan etkisinin olup olmayacağı benim için net bashdeğil (ama eğitimli bir tahmin yapmaz).


1
Kullanmadan RANDOMönce bir değeri bile var mı ? Her zaman sadece arandığında doldurulduğunu varsaydım.
terdon

1
Değil, bash el kitabı bundan bahseder.
terdon

1
Öyle yaparsanız export RANDOMveya declare -p RANDOMgörünürse de, bu yüzden başvuruda bulunmadan önce var olmadığından emin değilim ...
ilkkachu

1
“Bir çocuk sürecindeki değeri rastgele ancak statik olurdu.” Statik ise , üç bayt veya on altı olsun rastgele değildir .
l0b0

3
@ l0b0 Tahmin edemeyeceğiniz anlamıyla rastgele olurdu. Açıkçası, bir kere okuduğunuzda, değişmeyeceğinden artık rastgele değil (gösterdiğim şekilde yeniden dışa aktarmadığınız sürece, ortam değişkeni yeni bir rastgele değer elde eder). Bu yüzden rastgele ama statik dedim. Bunu şimdi metinde biraz açıklığa kavuşturdum.
Kusalananda

16

Shell oturumunuzda ayarlanan tüm değişkenler ortam değişkenleri değildir. "Ortam değişkenleri" yalnızca exportyerleşik yapıyı kullanarak çevreye verilen değişkenleri ifade eder . envKomut ancak böyle yazdırır ortam değişkenleri. Örneğin:

$ foo="bar"
$ env | grep foo ## returns nothing
$ export foo
$ env | grep foo ## now, env will print it
foo=bar

Oturumunuzda ayarlanan tüm değişkenleri görmek istiyorsanız, dışa aktarılıp aktarılmadıklarına bakılmaksızın, şunları kullanabilirsiniz set:

$ set | grep foo=
foo=bar

setBuiltin da böylece kullanabilirsiniz sadece değişkenleri görmek için, işlevlerini döndürür:

set | grep  '^[^[:space:]]*='

Son olarak, RANDOMdeğişken, yalnızca başvuru yaptığınızda bir değer atanması bakımından özeldir. Bu bash (1) de belirtilmiştir :

RANDOM

    Bu parametreye her başvuru yapıldığında, 0 ile 32767 arasında rastgele bir tam sayı üretilir. Rasgele sayılar dizisi, bir değer atanarak başlatılabilir RANDOM. Eğer RANDOMayarlanmazsa, bunun sonradan sıfırlanır bile, sahip olduğu özel nitelikleri kaybeder.

Dolayısıyla, düşündüğünüz gibi bir ortam değişkeni olsaydı bile, onu envilk aradığınıza kadar ayarlanmayacağından gösterilmeyecekti . Bu yüzden de gösterilmez set:

$ set | grep RAN   ## returns nothing, RANDOM is unset
$ echo "$RANDOM"   ## this will assign a value to RANDOM
1234
$ set | grep RAN   ## so now it will also appear in the output of set 
RANDOM=1234

Bununla ilgili ilginç bir keşif set | grep RAN. Beklemezdim. FWIW, belgelere göre tahmin edilemeyeceğine inanıyorum.
G-Man 'Reeantate Monica' Dedi

1
PS 120.000'e ulaştığınız için tebrikler. (Sanırım seni yeni koydum.)
G-Man 'Monica'yı yeniden yerleştir' diyor

4

Çoğu kabuk, varsayılan olarak alt işlemlere dışa aktarılmayan kabuk tarafından ayarlanan veya kullanılan birçok değişkene sahip olacaktır.

Bash'de belli ki Bash'e özgü olanlar var:

$ echo "${!BASH*}"
BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_CMDS BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
$ echo $BASH_VERSION
4.4.12(1)-release
$ env|grep -c BASH
0

Sonra daha standart olanları seviyorum var OPTINDve OPTERR(kullandığı getopts) ve PS2,PS3 : (ikincil istemleri) ve hatta başka "sihirli" değişken SECONDS(gösterir zaman saniyeler içinde kabuk başladığından beri)

Bash'de tüm değişkenleri ve bunların ihracat durumunu görebilirsiniz declare -p. İle işaretlenenler -xdışa aktarılır, olmayanlar dışa aktarılır x. (Bazılarının itam sayı veya rsalt okunur olması gibi başka bayrakları da vardır .)

Zsh veya ksh93 olarak, kullanabilirsiniz typeset -pdeğiştirerek olsa Zsh işaretleri ihraç değişkenleri typesetiçin exportçıktı, yerine bayraklarını kullanarak. exporttek başına dışa aktarılan tüm değişkenleri de gösterirdi, ancak bu, çalıştırarak elde ettiğiniz sonuçlarla ilgili env.


2

Bunun için google yaparsanız, dokümanlar şunları belirtir:

$RANDOM0 - 32767 aralığında bir psödorandom [1] tamsayı döndüren dahili bir Bash işlevidir (sabit değil) . Bir şifreleme anahtarı üretmek için kullanılmamalıdır.

Kullanırsanız strace, $RANDOM"değişkenin" doğrudan sıradan bir kabuk değişkeni veya bir ortam değişkenimiş gibi komutlara doğrudan iletildiğini görebilirsiniz , ancak bu yalnızca kabuğun içine yerleştirilmiş bir iç işlevdir, Bash, bu genişlemeyi gerçekleştirir.

$ strace -t echo "random value: $RANDOM"
04:37:58 execve("/bin/echo", ["echo", "random value: 30795"], [/* 27 vars */]) = 0
04:37:58 brk(NULL)                      = 0x19c1000
04:37:58 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9841351000
...

Bu normal değişkene karşı:

$ strace -t echo "random value: $SOMEVAR"
04:40:19 execve("/bin/echo", ["echo", "random value: helloworld"], [/* 27 vars */]) = 0
04:40:19 brk(NULL)                      = 0x154b000
04:40:19 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f659d2eb000
...

Değişken bir referans olarak aktarılmıyor.

Referanslar


1
peki, bu genişletilmiş değeri bir komut satırı argümanı üzerinden $RANDOMveya $SOMEVARbir ortam değişkeni olarak geçmemek değil mi? exportOnları çevreden geçirmek için ikisine de ihtiyacın var .
ilkkachu

Hayır, bu bir fark yaratmayacaktı. Kabuk ne olursa olsun onları genişletir. Gösterdiğim yol temel olarak kabuğun genişleme yaptığını vurgulamaktadır.
slm

2
straceÇıkış kabuk tarafından işletilen iç işlevini yakalamak için görünmüyor. Her iki durumda da, değişken ilk satırında zaten genişletildi strace. Hangi farkı işaret ettiğini anlamıyorum. Neyi kaçırıyorum?
terdon

Bu Gösterilen $RANDOMgenişleme kabuğuna içten yapılır. Temel olarak, kabuğun değeri belirlediği ve bir değişkene bir referans geçirmediği doğrulanır. Ayrıştırmayı yürütmek için komut satırını genişlettiğinde kabuk $RANDOM, genişletilmiş formu için iletir echo.
slm

2
O zaman, bir çevre değişkeni gibisi yok .
Toby Speight
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.