명령시 bash 스크립트의 임시 값


11

아래 명령과 같이

if true; then
   IFS=":" read a b c d e f <<< "$test"

이 책에서는 IFS ":"주 명령 ( read a b c d e f <<< "$value") 전에 값 할당 명령 ( )을 사용 하면 해당 값이 주 명령에 일시적으로 적용됩니다. 따라서 read명령은 delimiter를 사용 :합니다.

그러나이 명령처럼

if true; then
   HOME="hello" echo "$HOME"

에코 메시지는 안녕이 아닙니다. 위 명령의 실제 의미는 무엇입니까?

답변:


5

이것은 평가가 어떻게 작동하는지에 대한 질문으로 귀결됩니다. 두 예제 모두 같은 방식으로 작동하지만 셸 (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

여기서 작은 따옴표로 인해 변수가 아니라 변수가 새 프로세스로 전달됩니다.


7

쉘이 라인을 구문 분석 할 때, 라인을 단어로 토큰 화하고 단어에 대해 다양한 확장 (순서대로)을 수행 한 다음 명령을 실행합니다.

가정 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이 답이면 때로는 잘못된 질문을하는 것입니다. 그러나 어떤 이유로 누군가가 그렇게해야한다면 대답을 변경한다고해서 질문 자체가 덜 잘못되지는 않습니다. 또 다른 해결책은 함수로 감싸서 사용하는 것 local입니다.
— user23013

eval솔루션을 피해야 하는 이유는 무엇 입니까?
— DarkHeart

입력을 엄격하게 제어하지 않으면 다른 사람들이 프로그램에 삽입 할 수있는 코드에 매우주의해야합니다.
— glenn jackman 2:29에

-1

환경 변수와 로컬 변수의 두 가지 범위가 있습니다. 환경 변수는 모든 프로세스 (참조에 유효한 setenv, getenv로컬 변수는이 쉘 세션 내에서 활성 상태). (명백한 차이점은 아닙니다 ...)

암시 적으로 env(예와 같이) 환경을 수정 echo ...하고 로컬 환경을 사용하므로 env아무런 영향을 미치지 않습니다.

지역 변수를 수정하려면 다음과 같이 사용하십시오.

( HOME="foo" ; echo "$HOME" )

여기에서 괄호는이 과제의 범위를 정의합니다.


1
이것은 변수 범위와 아무 관련이 없으며, 문제는 변수가 자식 셸에 전달되기 전에 확장되고 있다는 것입니다.
— terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.