'RANDV'출력에 $ RANDOM이 포함되지 않은 이유는 무엇입니까?


23

env쉘 명령이라는 것을 알고 있습니다. 현재 환경 변수 목록을 인쇄하는 데 사용할 수 있습니다. 그리고 내가 이해 RANDOM하는 한 환경 변수이기도합니다.

그렇다면 왜 envLinux에서 시작할 때 출력에 포함되지 RANDOM않습니까?


4
env일반적으로 쉘에 내장되어 있지 않으므로 쉘 명령이 아닙니다.
schily

Bash의 @schily BTW declare -x는 쉘 내장의 것과 같습니다.
wjandrea

답변:


42

RANDOM환경 변수가 아닙니다. 일부 쉘이 유지 관리하는 쉘 변수입니다. 일반적으로 기본적으로 내보내지지 않습니다. 이것이의 출력에 표시되지 않는 이유입니다 env.

그것은 한 번에 적어도 사용 된 일단, 그것은 의 출력에 표시 set, 이는 그 자체로, 목록 현재 쉘 세션에서 쉘 변수 (및 기능)와 그 값. 이 동작은 쉘에 따라 다르며 pdkshOpenBSD에서 사용 하며 이전에 사용하지 않았더라도 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같은 변수 LINENO,SECONDS , BASHPID

환경 변수를 업데이트하려면 RANDOM에서를 bash, 당신은 그것을 쉘 변수의 값을 지정해야합니다 RANDOM 재수출을 :

export RANDOM="$RANDOM"

이것이 난수 생성기를 다시 시드하는 추가 부작용이 있는지 확실하지 bash않습니다 (그러나 교육받은 추측은 그렇지 않습니다).


1
않습니다 RANDOM당신이 그것을 사용하기 전에, 심지어 값이? 나는 항상 호출 할 때만 채워 졌다고 가정했습니다.
terdon

1
bash 매뉴얼에는 언급되어 있지 않습니다.
terdon

1
당신도 할 경우 비록 export RANDOM또는 declare -p RANDOM확실 그것이 참조되기 전에 존재하지 않는 어떤 사용의 경우 아니에요, 그래서 그것은 나타납니다 ...
ilkkachu

1
"자식 프로세스의 가치는 임의적이지만 정적입니다." 정적 인 경우 3 바이트이든 16 바이트이든 무작위가 아닙니다 .
l0b0

3
@ l0b0 예측할 수 없다는 의미에서 임의적입니다. 분명히, 일단 읽은 후에는 변경되지 않기 때문에 더 이상 무작위가 아닙니다 (필요에 따라 다시 내보내기하지 않으면 환경 변수가 새로운 임의 값을 얻습니다). 이것이 내가 무작위이지만 정적이라고 말한 이유입니다. 나는 지금 본문에서 이것을 분명히했다.
Kusalananda

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-남자 '는 분석 재개 모니카'말한다

1
추신 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

그리고이 같은 더 표준 것들의 OPTINDOPTERR(가 사용 getopts), 그리고 PS2, PS3(보조 프롬프트), 심지어 다른 "마법"변수 :SECONDS (쇼 시간을 초 쉘이 시작된 이후)

Bash에서는 모든 변수와 내보내기 상태를로 볼 수 있습니다 declare -p. 로 표시된 -x것은 내 보내지 않고없는 것으로 내 보냅니다 x. (일부 i정수 또는r 읽기 전용 습니다.

zsh을 또는 경우 ksh93에서는 사용할 수 typeset -p변경,하지만 zsh을 자국 내 보낸 변수 typesetexport출력에 대신 플래그를 사용하여. export자체적으로 내 보낸 모든 변수가 표시되지만을 실행하면 결과와 거의 같습니다 env.


2

이 작업을 Google에서 수행하면 문서에 다음 내용이 표시됩니다.

$RANDOM0-32767 범위 의 의사 난수 [1] 정수 를 반환 하는 내부 Bash 함수 (상수 아님)입니다 . 암호화 키를 생성하는 데 사용해서는 안됩니다.

사용 strace하면 $RANDOM"변수"가 일반 쉘 변수 또는 환경 변수 인 것처럼 명령에 직접 전달되는 것을 볼 수 있지만 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
...

변수가 참조로 전달되지 않습니다.

참고 문헌


1
물론, 그하지의 확장 된 값을 전달 $RANDOM하거나 $SOMEVAR환경 변수로 명령 행 인수를 통해, 그리고? export환경을 통해 전달 하려면 둘 다 필요 합니다.
ilkkachu

그것은 아무런 차이가 없습니다. 쉘은 관계없이 확장합니다. 내가 보여준 방법은 기본적으로 쉘이 확장하고 있다는 사실을 강조하는 것입니다.
slm

2
strace출력은 쉘에 의해 실행되는 내부 함수를 잡으려고하지 않는 것 같습니다. 두 경우 모두 변수는의 첫 번째 줄에서 이미 확장되었습니다 strace. 나는 당신이 어떤 차이를 가리키는 지 이해하지 못합니다. 내가 무엇을 놓치고 있습니까?
terdon

$RANDOM확장이 쉘 내부에서 수행 되었음을 표시합니다 . 기본적으로 쉘이 값을 결정하고 변수에 대한 참조를 전달하지 않는지 확인합니다. 쉘이 명령 행을 확장 할 때 구문 분석을 수행 $RANDOM하고 확장 된 양식을로 전달합니다 echo.
slm

2
따라서 환경 변수 와 같은 것은 없습니다 .
Toby Speight
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.