명령 행에서 환경 변수를 설정하고 명령에 표시하려면 어떻게합니까?


151

내가 달리면

export TEST=foo
echo $TEST

foo를 출력합니다.

내가 달리면

TEST=foo echo $TEST

그렇지 않습니다. 내보내기 또는 스크립트를 사용하지 않고 어떻게이 기능을 사용할 수 있습니까?


조심스럽게,이 이야기에는 처음 등장한 것보다 더 많은 것이 있습니다. 나는 당신이 내 대답을 확인하도록 초대합니다.
jasonleonhard

답변:


179

쉘 이 실제로 명령을 실행 하기 전에 명령 행에서 변수를 확장하고 그 때 변수가 존재하지 않기 때문입니다. 당신이 사용하는 경우

TEST=foo; echo $TEST

작동합니다.

export이후에 실행되는 명령의 환경에 변수가 표시됩니다 (bash에서 작동하는 방식에 대해서는 참조 help export). 하나의 명령 환경에 변수 만 나타나려면 시도한 것을 사용하십시오.

TEST=foo your-application

1
/ usr / bin / env는 어떻습니까? 작동하지 않습니다. 왜 그런지 아십니까?
Benubird

5
같은 이유- $TEST명령 행이 실행되기 전에 쉘이 확장됩니다 . 일단 echo실행 되면 ( echo일반적으로 셸 내장 명령으로 변환되고로 변환되지 않음 /bin/echo) 환경에서 변수 세트를 확인합니다. 그러나 환경에서 변수의 내용을 출력하도록 지시 echo $TEST하지 않습니다 . 쉘 은 현재 변수라는 변수에 인수가있는 것으로 실행하도록 지시합니다 .이 두 가지는 매우 다른 것입니다. echoTESTechoTEST
peterph

@peterph 쉘이 실제로 명령을 실행하기 전에 명령 행에서 변수를 확장하면 왜 확장되지 var=value sh -c 'echo "$var"'않습니까?
haccks

여기서 설명했듯이 : 변수는 큰 따옴표 (예 :) 안에 확장 "… $var …"되지만 작은 따옴표 (예 :) 안에는 확장되지 않기 때문 '… $var …'입니다. echo "$var"작은 따옴표 안에 있기 때문에 , 전체 문자열은 sh -c외부 대화식 쉘에 의해 해석되지 않고 새로운 ( ) 쉘로 전달됩니다 . … (계속)
G-Man

(계속)… igal이 어제 말했듯이 , igal은 귀하의 질문을 잘못 읽었다 고 믿지만, 두 번의 구문 분석이 있습니다. 부모 셸이 수행하는 구문 분석 외에 두 가지 구문 분석이 없습니다 . 외부, 대화식 (부모) 셸과 새 ( sh -c) 자식 셸에 의해 수행되는 두 가지 구문 분석이 있습니다 .
G-Man

39

환경 변수가 아닌 변수가 제한된 범위를 갖기 를 원한다고 생각합니다 . 환경 변수는 실행될 때 명령에 전달 된 문자열 목록입니다 .

에서

var=value echo whatever

var=value에코가 수신하는 환경으로 문자열을 전달합니다 . 그러나 echo환경 목록으로 아무 것도하지 않으며 대부분의 쉘에서 echo내장되어 실행 되지 않습니다 .

당신이 쓴 경우

var=value sh -c 'echo "$var"'

그것은 또 다른 문제 였을 것입니다. 여기서 우리는 명령을 전달 var=value하고 있으며 환경을 사용합니다. 셸은 환경에서받는 각 변수를 셸 변수 로 변환하므로 수신 되는 환경 변수 는 변수 로 변환 되고 해당 명령 줄 에서 변수가 확장 되면이 됩니다. 환경은 기본적으로 상속되므로 환경 에서도 수신 되지만 (또는 실행 된 경우) 환경에 신경 쓰지 않습니다.shshvarsh$varechoecho valueechovar=valueecho

내가 생각하기에 원하는 것은 쉘 변수의 범위를 제한하는 것입니다. 몇 가지 가능한 접근법이 있습니다.

휴대 가능 (Bourne 및 POSIX) :

(var=value; echo "1: $var"); echo "2: $var"

위의 (...)는 하위 쉘 (대부분의 쉘에서 새로운 쉘 프로세스)을 시작하므로 선언 된 모든 변수는 해당 하위 쉘에만 영향을 미치므로 위의 코드는 "1 : value"를 출력 할 것으로 예상됩니다. 및 "2 :"또는 "2 : whatever-var-was-set-to-before".

Bourne과 같은 대부분의 쉘에서 함수와 "로컬"내장 기능을 사용할 수 있습니다.

f() {
  local var
  var=value
  echo "1: $var"
}
f
echo "2: $var"

zsh를 사용하면 인라인 함수를 사용할 수 있습니다.

(){ local var=value; echo "1: $var"; }; echo "2: $var"

또는:

function { local var=value; echo "1: $var"; }; echo "2: $var"

bash 및 zsh (ash, pdksh 또는 AT & T ksh는 아님)를 사용하면이 트릭도 작동합니다.

var=value eval 'echo "1: $var"'; echo "2: $var"

몇 쉘에서 작동하는 변종 ( dash, mksh, yash)하지만 zsh(투입하지 않는 한 sh/ ksh에뮬레이션) :

var=value command eval 'echo "1: $var"'; echo "2: $var"

( POSIX 쉘에서 command특수 내장 (여기 eval) 앞에서 사용 하면 특수성이 제거됩니다 (여기서 변수 할당은 반환 된 후에도 유효합니다))


내 목적을 위해 이것이 올바른 해결책입니다. 허용 된 답변에서와 같이 변수 'var'이 환경을 오염시키지 않기를 바랍니다.
kronenpj

6

당신은 제대로 일을하고 있지만 bash는 구문이 잘못 해석하기 쉽다 : 당신이 생각할 수있는 echo $TEST원인 echo가져 TESTENV var에 다음을 인쇄, 그것은하지 않습니다. 그래서 주어진

export TEST=123

그때

TEST=456 echo $TEST

다음 순서를 포함합니다.

  1. 쉘은 전체 명령 행을 구문 분석하고 모든 변수 대체를 실행하므로 명령 행은

    TEST=456 echo 123
  2. 명령 전에 설정 한 임시 vars를 작성하므로 현재 값을 저장하고 TEST456으로 겹쳐 씁니다. 명령 행은 이제

    echo 123
  3. 나머지 명령을 실행합니다.이 경우 123을 stdout에 인쇄합니다 (따라서 남아있는 쉘 명령은 임시 값을 사용하지 않았습니다 TEST).

  4. 그것은의 가치를 복원 TEST

변수 대체를 포함하지 않으므로 printenv를 대신 사용하십시오.

>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>

+1 printenv테스트 / 개념 증명에 도움이되는 것으로 나타났습니다 (대신 스크립트와 달리 동작 echo)
Daryn

5

다음을 사용하여이 작업을 수행 할 수 있습니다.

TEST=foo && echo $TEST

6
이 경우 TEST=foo별도의 명령문으로 실행 중 echo입니다. 의 컨텍스트에서만 설정되지는 않습니다 .
codeforester 2018 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.