なぜ$ RANDOMが 'env'の出力に含まれないのですか?


23

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

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


4
env通常はシェルに組み込まれないため、シェルコマンドではありません。
気違い

Bashの@schily BTW declare -xは、シェル組み込みの同等のものです。
-wjandrea

回答:


42

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

それは少なくとも一度使用されていたら、それは考えの出力に表示さ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では、bashシェルアクセスは、その内部になりget_random()機能が変数に新しいランダムな値を与えることが、シェルは更新されない環境変数を RANDOM。これは、他の動的と同様の挙動に類似しているbashような変数、LINENOSECONDSBASHPID

環境変数更新するにはRANDOMではbash、あなたは、シェル変数の値を代入しなければならないRANDOM 再輸出にそれを:

export RANDOM="$RANDOM"

これに乱数ジェネレーターを再シードする追加の副作用bashがあるかどうかはわかりません(しかし、経験に基づいた推測はそうではないということです)。


1
RANDOMあなたがそれを使用する前にも、価値がありますか?呼び出されたときにのみデータが入力されると常に思っていました。
テルドン

1
そうではありません、bashのマニュアルではそれが言及されています。
テルドン

1
でも、export RANDOMまたはを行うとdeclare -p RANDOM、それが表示されるため、参照される前に存在しない使用であるかどうかは
わかり

1
「子プロセスの値はランダムですが、静的です。」静的な場合、 3バイトでも16バイトでも、ランダムではありません
l0b0

3
@ l0b0予測できないという意味ではランダムです。明らかに、一度読むと、変更されないのでランダムではありません(私が示したように再エクスポートしない限り、環境変数は新しいランダムな値を取得します)。これが、ランダムだが静的だと言った理由です。私はテキストでこれを幾分明確にしました。
クサラナナンダ

16

シェルセッションで設定されるすべての変数が環境変数であるとは限りません。「環境変数」とは、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変数は、参照するときにのみ値が割り当てられるという点で特別です。これはbash(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

それは興味深い発見set | grep RANです。私はそれを期待していなかっただろう。FWIW、ドキュメントでは予測できないと思います。
G-Manが「Reinstate Monica」と言う

1
PS 120,000に達しました。おめでとうございます。(私はちょうどあなたを置いたと思います。)
G-Manは「Reinstate Monica」と言います

4

ほとんどのシェルには、デフォルトで子プロセスにエクスポートされないシェルによって設定または使用される他の変数がいくつかあります。

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し、OPTERR(で使用されるgetopts)、およびPS2PS3(二次プロンプト)、さらには他の「マジック」変数SECONDS(シェルが起動してから数秒でショータイム)

Bashでは、すべての変数とそのエクスポートステータスをで確認できますdeclare -p。マークが付いて-xいるものはエクスポートされ、xないものはエクスポートされません。(i整数やr読み取り専用など、他のフラグを持つものもあります。)

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


2

これをグーグルで検索した場合、ドキュメントには次のように記載されています。

$RANDOM0〜32767の範囲の擬似乱数[1]整数を返す内部Bash 関数(定数ではありません)。暗号化キーの生成には使用しないでください。

使用straceすると、$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
...

変数は参照として渡されていません。

参照資料


1
まあ、それは環境変数としてではなく、コマンドライン引数の拡張値$RANDOMまたは$SOMEVARコマンドライン引数を介して渡されませんか?exportこれらを環境に渡すには両方が必要です。
-ilkkachu

いいえ、違いはありません。シェルは、関係なくそれらを展開します。私がそれを示した方法は、基本的にシェルが拡張を行っているという事実を強調しています。
slm

2
strace出力は、シェルによって実行内部関数をキャッチしていないようです。どちらの場合も、変数はの最初の行で既に展開されていますstrace。私はあなたが指している違いを理解していません。私は何が欠けていますか?
テルドン

ことを示す$RANDOM拡張がシェルに内部的に行われています。基本的には、シェルが値を決定し、変数への参照を渡さないことの確認です。シェルは、コマンドラインを展開して解析を実行し$RANDOM、展開されたフォームをに渡しechoます。
slm

2
したがって、環境変数のようなものはありません。
トビー・スペイト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.