Bash 매뉴얼은 다음과 같이 말합니다:
명령 대체, 괄호로 묶인 명령 및 비동기 명령은 쉘 환경과 중복되는 서브 쉘 환경에서 호출됩니다. 단, 쉘에 의해 잡힌 트랩은 쉘이 상위 쉘에서 상속받은 값으로 재설정됩니다. 기도.
이 예에서 는 b
환경 변수가 아니므로 b
명령 대체를 통해 생성된 하위 쉘에 존재하지 않습니다. 그렇다면 c
명령 대체를 통해 값을 할당하는 이유는 무엇입니까? 서브쉘이 생성되고 실행되기 전 쉘 프로세스에서 b
매개변수 확장이 일어나기 때문일까요 ?$b
echo 1
$ b=1
$ c=$(echo $b)
$ echo $c
1
답변1
아니요, 서브셸이 먼저 생성됩니다.
ㅏ쉘 실행 환경변수 할당 및 환경 변수로 설정된 쉘 매개변수를 포함합니다. 서브쉘 환경은 쉘 환경을 복사하여 생성되므로 현재 쉘 환경의 모든 변수를 포함합니다.
예를 참조하세요:
$ b=1
$ c=$(b=2; echo "$b")
$ echo "$c"
2
출력 2
은 1
.
명령 대체에 의해 생성된 서브쉘 환경은 쉘 실행 파일을 호출하여 생성된 쉘 환경과 다릅니다.
쉘을 호출할 때:
$ bash -c :
현재 사용중인 쉘구현하다()예를 들어 다음과 같이 새 셸 프로세스를 만듭니다.
execve("/bin/bash", ["bash", "-c", ":"], [/* 64 vars */]) = 0
전달된 마지막 매개변수에는 execve
모든 환경 변수가 포함됩니다.
그게 네가 필요한 이유야출구이후에 실행되는 명령에 포함될 환경 변수에 푸시하는 변수:
$ a=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
환경 변수가 64에서 65로 변경되었습니다. 그리고 내보내지 않은 변수는 새 셸 환경으로 전달되지 않습니다.
$ a=; b=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
환경 변수는 여전히 65입니다.
명령 대체에서 쉘은 다음을 사용합니다.십자가()변수 세트와 환경 변수를 포함하는 현재 쉘 환경을 단순히 복사하는 새로운 쉘 프로세스를 생성합니다.
답변2
예 b는 환경 변수가 아닙니다.
그러나 예, b는 명령 대체를 통해 생성된 하위 쉘에 존재합니다.
$ b=11; c="$(echo $b)"; echo "$c" ### b exists in subshell.
11
$ b=11; c="$(b=33; echo $b)"; echo "$c" ### $b is not replaced before
33 ### the subshell is executed.
무엇변수를 받지 못하는 것은 "완전한 하위 프로세스"입니다.:
$ b=11; bash -c 'echo "<$b>"' ### b does not exist.
<>
$ b=11 bash -c 'echo "<$b>"' ### environment b.
<11>
물론 해당 프로세스는 환경으로부터 변수를 받을 수 있다는 점은 제외됩니다.
마지막 줄은 다음 위치에 있습니다.울위치 달걀 껍질:
하위 쉘 내에서는 일반 쉘 변수 a가 표시되지만 내보내지지 않으므로 전체 하위 프로세스에는 표시되지 않습니다.
답변3
명령 대체로 인해 쉘 인터프리터가 정상적으로 호출되고 인터프리터 echo
는 sub-process
.
이는 셸이 결과를 읽을 수 있도록 명령을 sub-process
작성해야 하기 때문에 필요합니다 .pipe
echo
sub-process
이 명령을 실행하면 기본 셸 프로세스에 있는 모든 변수의 복사본이 생성됩니다 echo
. fork()
그렇기 때문에 명령을 $b
통해 액세스할 수 있습니다 .echo