私はenv
これが現在の環境変数のリストを印刷するために使用できるシェルコマンドであることを知っています。私が知る限り、RANDOM
それも環境変数です。
それでは、env
Linuxで起動したときに出力になぜ含まれないのですかRANDOM
?
答え1
RANDOM
環境変数ではありません。一部のシェルで維持するシェル変数です。デフォルトでは通常はエクスポートされません。これが出力に表示されない理由ですenv
。
1回以上使用すると会議に示されている出力自体には、set
現在のシェルセッションのシェル変数(および関数)とその値がリストされています。この動作はシェルによって異なり、pdksh
OpenBSD で使用され、RANDOM
以前に使用されていない場合でも一覧表示されます。set
RANDOM
この回答の残りの部分では、エクスポートされた場合(つまり、環境変数に切り替えられた場合)に発生する可能性があることについて説明します。
これをエクスポートするとexport RANDOM
環境変数になりますが、子プロセスの値は「ランダムですが静的」(不変の乱数になることを意味)なので、使用は厳しく制限されます。正確な動作はシェルによって異なります。
pdksh
OpenBSDで使用している以下の例では、awk
実行するたびに新しいランダムな値を取得します(ただし、同じ毎回同じインスタンスawk
の値)。を使用すると、bash
まったく同じランダムな値が得られます。みんな呼ぶawk
。
$ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }'
25444 25444
$ awk 'BEGIN { print ENVIRON["RANDOM"], ENVIRON["RANDOM"] }'
30906 30906
からbash
エクスポートされた値は、シェルで使用されている方法(使用するたびに新しい値を提供する)に関係なく静的に保持されます。RANDOM
RANDOM
$RANDOM
なぜなら、すべての言及シェル変数 RANDOM
inはbash
シェルが内部get_random()
関数にアクセスして変数に新しいランダムな値を割り当てるようにしますが、シェルは更新されません。環境変数 RANDOM
。これは他の動的bash
変数(例えばLINENO
、SECONDS
などBASHPID
)と同様に機能します。
RANDOM
環境変数を更新するには、bash
シェル変数の値を割り当てる必要があります。RANDOM
そして再エクスポート:
export RANDOM="$RANDOM"
これが乱数ジェネレータを再シードする追加の副作用があるかどうかはわかりませんbash
(しかし、訓練された推測はそうではありません)。
答え2
シェルセッションで設定されたすべての変数は環境変数ではありません。 「環境変数」は、組み込み関数を使用して環境にエクスポートした変数のみを参照しますexport
。このenv
コマンドは、次の内容を印刷します。環境変わりやすい。たとえば、
$ foo="bar"
$ env | grep foo ## returns nothing
$ export foo
$ env | grep foo ## now, env will print it
foo=bar
エクスポートしたかどうかにかかわらず、セッションに設定されているすべての変数を表示するには、次のものを使用できますset
。
$ set | grep foo=
foo=bar
組み込みset
関数も関数を返すので、利用可能な変数のみを表示するには、次の手順を実行します。
set | grep '^[^[:space:]]*='
最後に、このRANDOM
変数は参照時にのみ値が割り当てられる点で特別です。これは大きな打撃(1):
RANDOM
このパラメータが参照されるたびに、0から32767の間の任意の整数が生成されます。値を割り当てて一連の乱数を初期化できます。
RANDOM
。もしRANDOM
設定しないと、後でリセットしても特殊属性が失われます。
env
そのため、環境変数だと思っても最初に呼び出すまで設定されていないため表示されません。これが次の項目に表示されない理由でもあります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
答え3
ほとんどのシェルは、デフォルトで子プロセスにエクスポートされない他の多くの変数を設定または使用します。
Bashには、明らかにBashに固有のものがいくつかあります。
$ 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
OPTIND
次に、and OPTERR
(by getopts
)、and PS2
、PS3
(補助プロンプト)などのより多くの標準変数と別の「魔法」変数もありますSECONDS
。
Bashでは、すべての変数とそのエクスポートステータスを表示できますdeclare -p
。表示された項目はエクスポートさ-x
れ、表示されていない項目はエクスポートされx
ません。 (一部にはi
整数やr
読み取り専用などの他のフラグがあります。)
Zshまたはksh93では使用できますが、Zshはtypeset -p
フラグを使用する代わりに出力からに変更してエクスポートされた変数を表示します。それ自体は、エクスポートされたすべての変数も表示しますが、これは実行を通して得られるものとほぼ同じです。typeset
export
export
env
答え4
Googleで検索してみると、ドキュメントに次のようなものが表示されます。
$RANDOM
内部の Bash機能(定数ではない) 擬似乱数を返します。[1]0 ~ 32767 の範囲の整数です。暗号鍵の生成には使用しないでください。
を使用すると、「変数」が通常のシェル変数や環境変数であるかのようにコマンドに直接渡されるstrace
ことがわかりますが、これはシェルに組み込まれた内部関数にすぎず、Bashが拡張を行っています。$RANDOM
$ 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
...
この一般変数と比較すると、次のようになります。
$ 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
...
変数は参照に渡されません。