이 쉘/Bash 구문은 무엇입니까: someVariable=someValue someCommand [중복]

이 쉘/Bash 구문은 무엇입니까: someVariable=someValue someCommand [중복]

내 동료가 나에게 익숙하지 않은 Bash 구문을 제공했습니다. 내 Google foo는 그것이 무엇을 하는지, 왜/언제 사용해야 하는지 파악하지 못했습니다.

그가 나에게 보낸 명령은 이랬다.

someVariable=something command

처음에 나는 이것이 다음과 같다고 생각했습니다.

someVariable=something ; command

또는

someVariable=something 
command

그러나 그것은 사실이 아닌 것 같습니다. 예:

[Jan-03 11:26][~]$ # Look at the environment variable BAZ. It is currently empty
[Jan-03 11:26][~]$ echo $BAZ

[Jan-03 11:27][~]$ # Try running a command of the same format    
[Jan-03 11:27][~]$ BAZ=jake echo $BAZ

[Jan-03 11:27][~]$    
[Jan-03 11:27][~]$ # Now, echo BAZ again. It is still empty:    
[Jan-03 11:27][~]$ echo $BAZ

[Jan-03 11:27][~]$    
[Jan-03 11:28][~]$    
[Jan-03 11:28][~]$ # If we add a semi-colon to the command, we get dramatically different results:
[Jan-03 11:28][~]$ BAZ=jake ; echo $BAZ
jake
[Jan-03 11:28][~]$
[Jan-03 11:28][~]$ # And we can see that the variable is actually set:
[Jan-03 11:29][~]$ echo $BAZ
jake
[Jan-03 11:29][~]$

이 구문의 기능은 무엇입니까? 설정된 변수는 어떻게 되나요? 이것이 작동하는 이유는 무엇입니까?

답변1

이는 다음과 같습니다.

( export someVariable=something; command )

someVariable그러면 지정된 값을 사용하여 환경 변수가 생성되지만 실행 중인 명령에 대해서만 생성됩니다.

매뉴얼의 관련 부분은 다음과 같습니다 bash.

간단한 명령

간단한 명령은 순서이다선택적 변수 할당공백으로 구분된 단어와 리디렉션이 뒤따르고 제어 연산자로 종료됩니다. 첫 번째 단어는 실행할 명령을 지정하고 인수 0으로 전달됩니다. 나머지 단어는 호출된 명령에 인수로 전달됩니다.

(...)

간단한 명령 확장

[명령 확장]이 명령 이름을 생성하지 않는 경우 변수 할당은 현재 쉘 환경에 영향을 미칩니다. 그렇지 않으면,명령이 실행되는 환경에 변수가 추가되며 현재 쉘 환경에는 영향을 미치지 않습니다..

참고: 이는 에만 국한된 것은 bash아니지만POSIX에 의해 지정됨.


편집 - 답변의 의견에서 토론 요약

BAZ=JAKE echo $BAZJAKE가 인쇄되지 않는 이유는 변수 대체가 다른 것보다 먼저 수행되기 때문입니다. 변수 대체를 우회하면 예상대로 작동합니다.

$ echo_baz() { echo "[$BAZ]"; }
$ BAZ=Jake echo_baz
[Jake]
$ echo_baz
[]

답변2

이는 상황에 따른 변수 할당입니다.간단한 명령. ~처럼시안외부 명령의 경우 명령이 실행되는 동안 할당된 값을 내보내는 것과 동일하다고 언급되었습니다.

귀하의 예에서는 내장 명령을 사용하고 있으므로 동작이 정확히 동일하지 않습니다. 할당은 현재 환경에 영향을 주지만 내장 명령이 실행된 후에도 효과가 지속되는지 여부는 지정되지 않습니다. 예제를 이해하려면 변수가 처리되기 전에 매개변수 확장이 발생한다는 점을 알아야 합니다.

 BAZ=jake echo $BAZ

쉘은 먼저 확장되고 $BAZ(결과 없이) BAZ로 설정되고 jake마지막으로 실행됩니다.

 echo

빈 줄을 인쇄합니다. (나중에 표시된 BAZ것처럼 쉘은 잊어버립니다 echo $BAZ.)

 BAZ=jake; echo $BAZ

두 가지 명령으로 해석됩니다. 먼저 BAZ현재 환경에서 변수를 설정한 다음 echo $BAZ확장 echo jake하고 실행합니다.

답변3

여기서는 몇 가지 중요한 일이 일어나고 있습니다.

  • 설명된 대로배쉬 참조 매뉴얼, 간단한 명령 확장, "명령 이름 결과가 없으면 변수 할당은 현재 쉘 환경에 영향을 미칩니다. 그렇지 않으면,명령이 실행되는 환경에 변수가 추가됩니다.현재 쉘 환경에는 영향을 미치지 않습니다. "따라서 이라고 말하면 var="something" command arg1 arg2명령은 var명령 환경에서 실행되고 command종료 후에는 사라집니다. 이에 대한 데모는 간단합니다. 명령 내에서 명령 환경에 액세스합니다.

    $ BAZ="jake" python -c "import os; print os.environ['BAZ']"                                                              
    jake
    

    이것은 놀라운 일이 아닙니다. 이 구문은 수정된 환경에서 프로그램을 실행하는 데 자주 사용됩니다. unix.stackexchange.com 및 askubuntu.com 사용자는 다음 예를 인식할 것입니다. 사용자가 독일어 로케일을 사용하고 영어만 사용하는 경우 다음과 같이 발생하는 모든 문제를 재현하도록 요청하고 영어 출력을 얻을 수 있습니다.

    LC_ALL=C command
    

    또한 환경 액세스는 에만 국한되지 않으며 다른 프로그래밍 언어를 사용하여 수행 python할 수 있습니다 . C그것은 이제 제가 "선택한 무기"가 되었으며 이 데모에만 사용됩니다.

  • 변수 확장은 실행 전에 발생합니다. 따라서 유사한 명령을 실행할 때 BAZ="foo" echo $BAZ쉘은 먼저 해당 환경을 살펴보고 변수 BAZ가 없음을 확인하므로 비어 있습니다 $BAZ. 간단한 데모는 다음과 같습니다.

    $ BAZ="jake" python -c "import sys; print 'ARG:',sys.argv[1]" $BAZ                                                       
    ARG:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    IndexError: list index out of range
    

또한 차이점은 쉘 환경에 남아 있는 BAZ=jake; echo $BAZ두 개의 별도 명령문이라는 점에 유의하십시오. BAZ=jake사용 사례는 의도에 따라 다릅니다. 이러한 변수가 필요한 여러 프로그램을 실행하려는 경우 해당 변수가 필요할 수 있습니다 export. 이 특정 시간에만 필요한 경우 변수를 미리 할당하는 것이 더 나을 수 있습니다.

답변4

간단히 말해서:

BAZ=jake echo $BAZ

variable substitution가 명령에서 먼저 발생하므로 아무것도 출력되지 않습니다 . 이는 이 명령줄에서 발생하는 첫 번째 작업이 이전에 정의된 변수(있는 경우)의 실제 값 $BAZ으로 대체된다는 의미입니다. BAZ이는 쉘이 BAZ=jake동일한 명령줄을 고려하기도 전에 발생합니다.

Since는 명령이 실행되기 전에는 어떤 값도 할당되지 않으며 , 이후는 BAZ구문 분석 BAZ=jake후에만 고려되므로 어떤 값으로도 확인되지 않습니다. 따라서 아무것도 출력되지 않습니다.$BAZ$BAZecho $BAZ

BAZ=jake주어진 명령의 일부일 뿐입니다(셸은 이를 환경 변수로 처리/설정하지 않습니다). 이 변수는 일부 프로세스가 동일한 명령줄의 일부로 실행될 때 사용되며 이는 유용합니다 BAZ. 명령 실행이 완료되면 BAZ의 값이 불안정해집니다.jake

예를 들어:]# LD_LIBRARY_PATH="new_path" ldconfig, 어디ldconfig변수는 명령에 의해 내부적으로 참조되며 LD_LIBRARY_PATH, 위와 달리 이 명령줄에는 변수 확장이 없습니다.

다른 경우:

BAZ=jake; echo $BAZ  

한 줄에 제공되는 두 가지 다른 명령입니다. 그것은 하나의 작업을 차례로 수행하는 것과 같습니다.

관련 정보