답변:
이것은 평가가 어떻게 작동하는지에 대한 질문으로 귀결됩니다. 두 예제 모두 같은 방식으로 작동하지만 셸 (bash, here)이 변수를 확장하는 방식으로 인해 문제가 발생합니다.
이 명령을 작성할 때 :
HOME="foo" echo $HOME
는 $HOME확장 명령이 실행되기 전에 . 따라서 명령에 대해 설정 한 새 값이 아니라 원래 값으로 확장됩니다. HOME변수는 실제로 그 환경에서 변경되었습니다 echo명령은 그러나, 당신은을 인쇄에서 실행 $HOME부모에서.
설명하기 위해 이것을 고려하십시오.
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
위에서 볼 수 있듯이 첫 번째 명령은 일시적으로 변경된 값을 HOME인쇄하고 두 번째 명령 은 원본을 인쇄하여 변수가 일시적으로 만 변경되었음을 보여줍니다. 때문에 bash -c ...명령 (작은 따옴표로 묶여 ' '대신 두 사람 (의) " "), 변수는 확장되지 않은 새로운 bash는 프로세스에 그대로 전달됩니다. 그런 다음이 새 프로세스는 프로세스를 확장하고 설정된 새 값을 인쇄합니다. 다음을 사용하면 이런 일이 발생할 수 있습니다 set -x.
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo hello
hello
위에서 볼 수 있듯이 변수 $HOME 는에 전달되지 않습니다 echo. 확장 된 값만 볼 수 있습니다. 다음과 비교하십시오 :
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
여기서 작은 따옴표로 인해 변수가 아니라 변수가 새 프로세스로 전달됩니다.
쉘이 라인을 구문 분석 할 때, 라인을 단어로 토큰 화하고 단어에 대해 다양한 확장 (순서대로)을 수행 한 다음 명령을 실행합니다.
가정 test=1:2:3:4:5:6
이 명령을 보자 : IFS=":" read a b c d e f <<< "$test"
토큰 화 후 매개 변수 확장이 발생합니다.IFS=":" read a b c d e f <<< "1:2:3:4:5:6"
쉘은 read 명령 기간 동안 IFS 변수를 설정하고 read$ IFS를 입력에 적용 하고 변수 이름에 값을 제공 하는 방법을 알고 있습니다.
이 명령은 비슷한 이야기이지만 다른 결과가 있습니다. HOME="hello" echo "$HOME"
명령이 시작 되기 전에 매개 변수 확장이 발생하므로 쉘에는 다음이 있습니다.
HOME="hello" echo "/home/username"
그런 다음 echo 명령을 실행하는 동안 $ HOME의 새 값이 전혀 사용되지 않습니다.
수행하려는 작업을 수행하려면 다음 중 하나를 선택하십시오.
# Delay expansion of the variable until its new value is set
HOME="hello" eval 'echo "$HOME"'
또는
# Using a subshell, so the altered env variable does not affect the parent.
# The semicolon means that the variable assignment will occur before
# the variable expansion
(HOME="hello"; echo "$HOME")
그러나 첫 번째 것을 선택하지 마십시오.
eval솔루션을 피해야 하는 이유는 무엇 입니까?
환경 변수와 로컬 변수의 두 가지 범위가 있습니다. 환경 변수는 모든 프로세스 (참조에 유효한 setenv, getenv로컬 변수는이 쉘 세션 내에서 활성 상태). (명백한 차이점은 아닙니다 ...)
암시 적으로 env(예와 같이) 환경을 수정 echo ...하고 로컬 환경을 사용하므로 env아무런 영향을 미치지 않습니다.
지역 변수를 수정하려면 다음과 같이 사용하십시오.
( HOME="foo" ; echo "$HOME" )
여기에서 괄호는이 과제의 범위를 정의합니다.
local입니다.