「env」出力に$RANDOMが含まれていないのはなぜですか?

「env」出力に$RANDOMが含まれていないのはなぜですか?

私はenvこれが現在の環境変数のリストを印刷するために使用できるシェルコマンドであることを知っています。私が知る限り、RANDOMそれも環境変数です。

それでは、envLinuxで起動したときに出力になぜ含まれないのですかRANDOM

答え1

RANDOM環境変数ではありません。一部のシェルで維持するシェル変数です。デフォルトでは通常はエクスポートされません。これが出力に表示されない理由ですenv

1回以上使用すると会議に示されている出力自体には、set現在のシェルセッションのシェル変数(および関数)とその値がリストされています。この動作はシェルによって異なり、pdkshOpenBSD で使用され、RANDOM以前に使用されていない場合でも一覧表示されます。set


RANDOMこの回答の残りの部分では、エクスポートされた場合(つまり、環境変数に切り替えられた場合)に発生する可能性があることについて説明します。

これをエクスポートするとexport RANDOM環境変数になりますが、子プロセスの値は「ランダムですが静的」(不変の乱数になることを意味)なので、使用は厳しく制限されます。正確な動作はシェルによって異なります。

pdkshOpenBSDで使用している以下の例では、awk実行するたびに新しいランダムな値を取得します(ただし、同じ毎回同じインスタンスawkの値)。を使用すると、bashまったく同じランダムな値が得られます。みんな呼ぶawk

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

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

からbashエクスポートされた値は、シェルで使用されている方法(使用するたびに新しい値を提供する)に関係なく静的に保持されます。RANDOMRANDOM$RANDOM

なぜなら、すべての言及シェル変数 RANDOMinはbashシェルが内部get_random()関数にアクセスして変数に新しいランダムな値を割り当てるようにしますが、シェルは更新されません。環境変数 RANDOM。これは他の動的bash変数(例えばLINENOSECONDSなど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 PS2PS3(補助プロンプト)などのより多くの標準変数と別の「魔法」変数もありますSECONDS

Bashでは、すべての変数とそのエクスポートステータスを表示できますdeclare -p。表示された項目はエクスポートさ-xれ、表示されていない項目はエクスポートされxません。 (一部にはi整数やr読み取り専用などの他のフラグがあります。)

Zshまたはksh93では使用できますが、Zshはtypeset -pフラグを使用する代わりに出力からに変更してエクスポートされた変数を表示します。それ自体は、エクスポートされたすべての変数も表示しますが、これは実行を通して得られるものとほぼ同じです。typesetexportexportenv

答え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
...

変数は参照に渡されません。

引用する

関連情報