명령시 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.