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
无论RANDOM
shell中使用的是什么,的导出值都将保持静态(其中每次使用$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中。