환경 변수를 지정하고 동일한 명령줄에서 에코할 수 없는 이유는 무엇입니까?
다음 부분을 고려해 보십시오.
$ SOMEVAR=AAA
$ echo zzz $SOMEVAR zzz
zzz AAA zzz
여기 기기팅팅세 here here here here를 설정했습니다.$SOMEVAR
로로 이동합니다.AAA
에 - 그리고 두 번째 줄에 반향하면 - 네, 네, 네, 이렇게 나옵니다.AAA
예상대로입니다.
그런 다음 변수를 같은 명령줄에 요.echo
다음을 참조하십시오
$ SOMEVAR=BBB echo zzz $SOMEVAR zzz
zzz AAA zzz
...전혀 이해가 안 돼요BBB
- 옛날 값(예상대로 - 옛날 값)이 나오네요.AAA
를 참조하십시오.
래래이? 이?? ????그렇다면 어떻게 하다, 하다, 하다, 하다 같은 변수를 지정할 수 있을까요?LD_PRELOAD=/... program args ...
효과가 있을까요?가가무 무무 ?? ??? ??? ???
이겁니다.문제는 부모 껍데기가 평가한다는 것입니다.$SOMEVAR
명령줄이 수정된 환경에서 명령을 호출하기 전에 명령줄을 클릭합니다.평가를 받아야 합니다.$SOMEVAR
이겁니다.
즉시 옵션은 다음과 같습니다.
SOMEVAR=BBB eval echo zzz '$SOMEVAR' zzz
요.SOMEVAR=BBB sh -c 'echo zzz $SOMEVAR zzz'
요.
둘 다 작은 따옴표를 사용하여 부모 셸이 평가하지 못하도록 합니다.$SOMEVAR
; 환경에서 설정된 후에만 평가됩니다(단일 명령의 지속 시간 동안 일시적으로).
또 다른 옵션은 하위 셸 표기법(Marcus Kuhn의 답변에서도 제안됨)을 사용하는 것입니다.
(SOMEVAR=BBB; echo zzz $SOMEVAR zzz)
변수는 하위 셸에서만 설정됩니다.
문제, 다시 방문했습니다.
솔직히 설명서는 이 점에서 혼란스럽습니다.GNU Bash 설명서에는 다음과 같이 나와 있습니다.
Shell Parameters(쉘 매개 변수)에 설명된 대로 매개 변수 할당 앞에 간단한 명령 또는 기능을 추가할 수 있습니다.이러한 할당 문은 해당 명령에 의해 표시되는 환경에만 영향을 미칩니다.
문장을 실제로 구문 분석하면 명령/함수의 환경은 수정되지만 상위 프로세스의 환경은 수정되지 않습니다.이렇게 하면 됩니다.
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
env 명령이 실행되기 전에 환경이 수정되었기 때문입니다.그러나 이 방법은 작동하지 않습니다.
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
셸에 의해 매개 변수 확장이 수행되기 때문입니다.
인터프리터 단계입니다.
문제의 또 다른 부분은 Bash가 인터프리터에 대해 다음과 같은 단계를 정의한다는 것입니다.
- 파일(Shell 스크립트 참조), -c 호출 옵션에 인수로 제공된 문자열(Bash 호출 참조) 또는 사용자 터미널에서 입력을 읽습니다.
- 견적에 설명된 견적 규칙을 준수하여 입력을 단어와 연산자로 나눕니다.이러한 토큰은 메타 문자로 구분됩니다.별칭 확장은 이 단계에서 수행됩니다(별명 참조).
- 토큰을 단순 및 복합 명령으로 구문 분석합니다(쉘 명령 참조).
- 다양한 셸 확장을 수행하고(Shell Expansions 참조), 확장된 토큰을 파일 이름 목록(파일 이름 확장 참조), 명령 및 인수 목록으로 나눕니다.
- 필요한 리디렉션을 수행하고( 리디렉션 참조) 리디렉션 연산자와 해당 피연산자를 인수 목록에서 제거합니다.
- 명령을 실행합니다(명령 실행 참조).
- 선택적으로 명령이 완료될 때까지 기다렸다가 종료 상태를 수집합니다(종료 상태 참조).
즉, 빌트인은 자체 실행 환경을 구축하지 않기 때문에 수정된 환경을 볼 수 없습니다.또한 간단한 명령(예: /bin/echo)은 수정된 환경(예: env 예제가 작동한 이유)을 얻지만 셸 확장은 4단계에서 현재 환경에서 수행됩니다.
즉, 'aaa $TESTVAR ccc'를 /bin/echo로 전달하는 것이 아니라 현재 환경에서 확장된 보간 문자열을 /bin/echo로 전달하는 것입니다.이 경우 현재 환경에 TESTVAR가 없으므로 'aaa ccc'를 명령에 전달하기만 하면 됩니다.
요약
서류는 훨씬 더 명확할 수 있습니다.스택 오버플로가 있어서 다행이에요!
참고 항목입니다.
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment
원하는 것을 달성하려면 다음을 사용하십시오.
( SOMEVAR=BBB; echo zzz $SOMEVAR zzz )
이유는 다음과 같습니다.
할당은 세미콜론 또는 새 줄로 다음 명령에서 구분해야 합니다. 그렇지 않으면 다음 명령(에코)에 대해 매개 변수 확장이 발생하기 전에 실행되지 않습니다.
하위 셸 환경 내에서 할당이 현재 줄을 초과하여 지속되지 않도록 해야 합니다.
이 솔루션은 다른 솔루션보다 더 짧고, 더 깔끔하고, 더 효율적이며, 특히 새로운 프로세스를 생성하지 않습니다.
POSIX 규격을 참조하여 bash뿐만 아니라 호환 셸에서도 왜 이렇게 동작하는지 알아보겠습니다.
2.10.2 셸 문법 규칙입니다.
규칙 7(b)에서, 할당이 간단한 명령 앞에 오는 경우를 다룹니다.
'=' 앞의 모든 문자가 유효한 이름을 형성하는 경우(IEEE 규격 1003.1-2001의 기본 정의 볼륨, 섹션 3.230, 이름 참조), 토큰 AJSignment_WORD가 반환됩니다.(따옴표로 묶은 문자는 올바른 이름 형성에 참여할 수 없습니다.)
[...]
NAME에 대한 할당은 Simple Commands에 지정된 대로 이루어져야 합니다.
따라서 POSIX 호환 셸의 경우 이 할당을 구문 분석해야 합니다.
2.9.1, 간단한 명령입니다.
리디렉션은 리디렉션에 설명된 대로 수행해야 합니다.
각 변수 할당은 값을 할당하기 전에 칠드 확장, 매개 변수 확장, 명령 대체, 산술 확장 및 견적 제거를 위해 확장되어야 합니다.
[...]
명령 이름이 나타나지 않으면 변수 할당이 현재 실행 환경에 영향을 미칩니다.그렇지 않으면 변수 할당은 명령 실행 환경에 대해 내보내야 하며 현재 실행 환경(특수 내장 제외)에 영향을 미치지 않습니다.변수 할당 중 하나가 읽기 전용 변수에 값을 할당하려고 하면 변수 할당 오류가 발생합니다.이러한 오류의 결과는 셸 오류의 결과를 참조하십시오.
따라서: 단순 명령에 대한 접두사 일부에 지정된 할당은 내보내야 하며 호출되는 명령이 특별한 기본 제공 명령이 아닌 한 "현재 셸 환경"에 영향을 미치지 않아야 합니다.또한 이러한 단계는 기본적으로 명령 호출 프로세스에서 늦게 발생하는 리디렉션을 따라야 합니다.
2.12, 셸 실행 환경입니다.
특수 빌트인 이외의 유틸리티(특수 빌트인 유틸리티 참조)는 다음과 같이 구성된 별도의 환경에서 호출해야 합니다.이러한 개체의 초기 값은 아래에 명시된 경우를 제외하고 상위 셸의 값과 동일해야 합니다.
[...]
내보내기 속성이 있는 변수와 명령 기간 동안 명시적으로 내보낸 변수를 함께 유틸리티 환경 변수로 전달해야 합니다.
따라서: 이러한 변수는 포크 후 및 호출되는 명령을 실행하기 전에 하위 셸에 의해 확장되며, 사양에 따라 하위 환경에만 영향을 주어야 합니다.
다른 동작의 경우 다음과 같습니다.
SOMEVAR=BBB sh -c 'echo "$SOMEVAR"'
...의 이점입니다.sh
시작할 때 환경 변수에서 셸 변수를 생성하는 인스턴스(POSIX 규격의 섹션 2.5.3에 필요)입니다.
참고로, 요청하신 구문은 하위 셸 내의 할당이 아니라 단순한 명령 내의 할당입니다.파이프라인에 포함된 하위 쉘에서 다음과 같이 할당을 제어할 수 있습니다.
{ SOMEVAR=BBB; echo "$SOMEVAR"; } | somecommand ...
...파이프라인의 첫 번째 구성 요소를 실행하는 하위 쉘에 할당을 넣습니다(쉘이 하위 쉘에서 해당 구성 요소를 실제로 실행하고 있는 경우, POSIX와 관련하여 정의되지 않은 동작). 사양에서 "단, 파이프라인의 일부 또는 모든 명령이 현재 환경에서 실행될 수 있습니다."
그 이유는 이렇게 하면 한 줄에 환경 변수가 설정되기 때문입니다.그렇지만,echo
확장이 되지 않습니다.bash
따라서 명령이 실행되기 전에 변수가 실제로 확장됩니다.SOME_VAR
이에요BBB
echo 명령의 컨텍스트에서 사용합니다.
효과를 보려면 다음과 같은 작업을 수행할 수 있습니다.
$ SOME_VAR=BBB bash -c 'echo $SOME_VAR'
BBB
여기서 변수는 하위 프로세스가 실행될 때까지 확장되지 않으므로 업데이트된 값이 표시됩니다.확인해보시면요SOME_VARIABLE
다시 부모 셸에, 여전히 남아 있습니다.AAA
예상대로입니다.
간단히 말해, 그.$SOMEVAR
미리 준비하는 동안 명령이 호출되기 전에 평가됩니다.SOMEVAR=BBB
명령 앞에 있는 를 누르면 실행 중인 명령의 환경이 수정됩니다.
찰스 더피가 말했듯이, 중간물질을 첨가할 수 있습니다.sh
유사한 구문을 사용하여 변수를 평가하지만 좀 더 정교한 작업을 수행해야 할 수 있습니다. 이 프로세스에서 여전히 문제가 발생할 경우 어떻게 해야 하는지 알아두는 것이 유용할 수 있습니다.
SOMEVAR=BBB; echo zzz $SOMEVAR zzz
같은 줄에 있는 문을 구분하려면 , 를 사용합니다.
SOMEVAR=BBB echo zzz $SOMEVAR zzz
추가할 것입니다.SOMEVAR=BBB
환경 변수로 변환한 다음 실행합니다.echo zzz $SOMEVAR zzz
.그$SOMEVAR
셸 변수를 참조합니다.SOMEVAR
설정했습니다.AAA
미리 확인하세요.
세미 콜론을 추가합니다.SOMEVAR=BBB; echo zzz $SOMEVAR zzz
셸 변수를 다음과 같이 설정합니다.BBB
그리고 나서 반감시 후에 명령을 실행합니다.echo zzz $SOMEVAR zzz
생산합니다.zzz BBB zzz
요.
다음 명령을 사용해 보십시오.
SOMEVAR=BBB env | less
그리고 환경을 보세요.
한 가지 대안이 있습니다.
SOMEVAR=BBB && echo zzz $SOMEVAR zzz
언급URL : https://stackoverflow.com/questions/10938483/why-cant-i-specify-an-environment-variable-and-echo-it-in-the-same-command-line 입니다.
'programing' 카테고리의 다른 글
@viewchild를 사용하여 여러 뷰 하위 항목에 액세스합니다. (0) | 2023.04.25 |
---|---|
Eclipse에서 프로젝트를 그룹화할 수 있습니까? (0) | 2023.04.25 |
'--no-ff' 플래그는 'git merge'에 어떤 영향을 미칩니까? (0) | 2023.04.25 |
Angular 2에서 입력 태그 파일 형식으로 선택한 파일을 재설정하려면 어떻게 해야 합니까? (0) | 2023.04.25 |
CGPoint 개체를 NSAray에 쉽게 추가하려면 어떻게 해야 합니까? (0) | 2023.04.25 |