Answers:
RANDOM不是环境变量。这是由一些shell维护的shell变量。默认情况下,通常不导出它。这就是为什么它不会出现在的输出中的原因env。
一旦它已经至少使用过一次,它会在输出显示出来set,这本身并列出了shell变量(和函数)和它们的值在当前shell会话。此行为取决于外壳程序,并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无论RANDOMshell中使用的是什么,的导出值都将保持静态(其中每次使用$RANDOM仍将提供新值)。
这是因为每个参考shell变量 RANDOM在bash使shell访问其内部get_random()功能来给变量赋新的随机值,但外壳不更新环境变量 RANDOM。这是因为与其他动态行为类似的bash变量,例如LINENO,SECONDS,BASHPID等。
要更新环境变量RANDOM中bash,你将不得不为它分配shell变量的值,RANDOM 并重新将其导出:
export RANDOM="$RANDOM"
我不清楚这是否会对重新植入随机数生成器产生其他副作用bash(但有根据的猜测是,事实并非如此)。
RANDOM连一个值然后再使用它?我一直以为只在调用时填充它。
export RANDOM或declare -p RANDOM,它会出现,所以我不确定在引用之前它是否不存在它的任何用途……
并非在Shell会话中设置的所有变量都是环境变量。“环境变量”仅指已使用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,我相信文档无法预测。
大多数Shell会设置一些其他变量,这些变量由Shell设置或使用,默认情况下不会导出到子进程。
在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),和PS2,PS3(辅助提示),甚至还有另一个“魔术”变量:(SECONDS以秒为单位显示自启动外壳以来的时间)
在Bash中,您可以使用查看所有变量及其导出状态declare -p。标-x有的将被导出,没有标出的x将不被导出。(有些标志将带有其他标志,例如i整数或r只读标志。)
在Zsh或ksh93中,可以使用typeset -p,尽管Zsh通过在输出中更改typeset为标记导出的变量export,而不是使用标志。export本身也会显示所有导出的变量,但这与通过运行获得的结果大致相同env。
如果您用谷歌搜索,文档说明以下内容:
$RANDOM是一个内部Bash 函数(不是常量),它返回0到32767范围内的伪随机[1]整数。不应将其用于生成加密密钥。
如果使用的strace话,您会看到$RANDOM“变量”被直接传递给命令,就像它是任何普通的shell变量或环境变量一样,但这只是内置在shell Bash中的内部函数,它在进行扩展。
$ 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
...
该变量未作为参考传递。
$RANDOM或$SOMEVAR通过命令行参数传递,而不是作为环境变量传递吗?您需要export同时使它们通过环境。
strace输出似乎没有赶上通过shell中运行的内部功能。在这两种情况下,变量都已经在的第一行中进行了扩展strace。我不明白您要指的是什么。我想念什么?
$RANDOM扩展是在shell内部完成的。基本上可以确认shell正在确定值,而不是将引用传递给变量。外壳程序在扩展命令行以执行解析$RANDOM并将扩展形式传递给时echo。
env不是shell命令,因为它通常不内置在shell中。