내가 달리면
export TEST=foo
echo $TEST
foo를 출력합니다.
내가 달리면
TEST=foo echo $TEST
아니요. 내보내기나 스크립트를 사용하지 않고 이 기능을 얻으려면 어떻게 해야 합니까?
답변1
이는 쉘이 명령줄에서 변수를 확장하기 때문입니다.앞으로실제로 명령을 실행하지만 이 시점에서는 변수가 존재하지 않습니다. 당신이 사용하는 경우
TEST=foo; echo $TEST
작동합니다.
export
이후에 실행되는 명령의 환경에 변수가 나타나게 됩니다(bash 에서 이것이 어떻게 작동하는지에 대한 정보는 참조 help export
). 하나의 명령 환경에만 변수가 표시되어야 하는 경우 시도한 방법을 사용하십시오.
TEST=foo your-application
쉘 구문은 이를 다음과 같이 설명합니다.기능적으로다음과 동일:
export TEST=foo
your-application
unset TEST
바라보다사양더 알아보기.
흥미롭게도 이 export
명령은 변수의 내보내기 플래그를 토글합니다.이름. 그렇다면 다음과 같이 하세요.
unset TEST
export TEST
TEST="foo"
TEST
내보내기 시 정의되지 않은 경우에도 내보내집니다. 그러나 unset
내보낸 속성은 여기서 제거해야 합니다.
답변2
당신이 갖고 싶어하는 것 같아요껍데기변수는 환경 변수가 아닌 제한된 범위를 갖습니다. 환경 변수는 명령에 전달된 문자열 목록입니다.처형된.
존재하다
var=value echo whatever
var=value
문자열을 에코 수신 환경에 전달합니다 . 그러나 echo
환경 목록에는 아무 작업도 수행되지 않으며 대부분의 셸에는 echo
어쨌든 내장되어 있으므로 그렇게 하지 않습니다.처형된.
당신이 썼다면
var=value sh -c 'echo "$var"'
그것은 또 다른 이야기입니다. 여기서는 명령을 전달하고 var=value
해당 환경 을 사용하게 됩니다. 쉘은 환경에서 받은 모든 변수를 쉘 변수로 변환하므로 받은 환경 변수는 변수 로 변환되고 해당 명령줄에서 확장하면 환경이 기본적으로 상속 되므로 가 됩니다 . 또한 해당 환경에서 수신되지만(또는 실행되는 경우) 환경에 대해서는 신경 쓰지 않습니다.sh
sh
var
sh
$var
echo
echo value
echo
var=value
echo
이제 제가 생각하는 것처럼 쉘 변수의 범위를 제한하려는 경우 몇 가지 가능한 방법이 있습니다.
휴대용(Bourne 및 POSIX):
(var=value; echo "1: $var"); echo "2: $var"
(...) 위는 서브쉘(대부분의 쉘에서 새로운 쉘 프로세스)을 시작하므로 여기에 선언된 모든 변수는 해당 서브쉘에만 영향을 미치므로 위의 코드에서 "1: value" 및 " 2:" 또는 " 2: 이전에 설정된 모든 변수".
대부분의 Bourne형 쉘의 경우(참조지역 변수를 정의하기 위해 "local" 키워드를 지원하는 쉘 목록), 함수와 "로컬" 내장 기능을 사용할 수 있습니다.
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
특수성이 제거됩니다(여기서 선행 변수 할당은 반환 후에도 유효합니다).
fish
셸을 사용하면 변수를 begin
.. end
블록에 로컬로 설정할 수 있습니다.
begin
set -l var value
echo 1: $var
end
echo 2: $var
mksh
(그리고 곧 zsh를 사용 하면 ${|cmd}
로컬 범위도 가질 수 있는 이 구성을 남용하여 $REPLY
다음 범위에서 설정하지 않도록 하여 null로 확장되도록 할 수 있습니다.
${|local var=value; echo "$var"}; echo "$var"
엄밀히 말하면 이것은 전적으로 사실이 아닙니다. 일부 구현은 지역화된 환경 변수( LANG
, LOCPATH
, LC_*
...)에 관심을 갖고, GNU 구현은 POSIXLY_CORRECT
환경 변수( GNU 시스템과 달리) env echo --version
에 관심을 갖습니다.env POSIXLY_CORRECT=1 echo --version
답변3
올바르게 수행하고 있지만 bash 구문은 쉽게 오해됩니다. 이렇게 하면 env var를 가져온 다음 인쇄하게 echo $TEST
될 것이라고 생각할 수도 있지만 그렇지 않습니다. 그래서 주어진echo
TEST
export TEST=123
그 다음에
TEST=456 echo $TEST
다음 순서가 포함됩니다.
쉘은 전체 명령줄을 구문 분석하고 모든 변수 대체를 수행하므로 명령줄은 다음과 같습니다.
TEST=456 echo 123
명령 이전에 임시 변수 세트를 생성하므로 현재 값을 저장하고
TEST
이제 명령줄을 456으로 덮어씁니다.echo 123
나머지 명령을 실행합니다. 이 경우 표준 출력에 123을 인쇄합니다(따라서 나머지 쉘 명령에는 임시 값이 사용되지도 않습니다
TEST
).가치를 회복시켜준다
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
>>
답변4
이미 발견한 바와 같이, Bash에서는 TEST=456 echo $TEST
쉘이 현재 해석하고 있는 동일한 행의 변수에 액세스하고 있기 때문에 예상대로 작동하지 않습니다. 하지만 걱정하지 마세요. 변수는 현재 명령이 지속되는 동안 설정됩니다. 이를 확인하려면 다음을 수행할 수 있습니다.
show () { echo "${!1}" ;}
TEST=456 show TEST