programing

환경 변수를 지정하고 동일한 명령줄에서 에코할 수 없는 이유는 무엇입니까?

showcode 2023. 4. 25. 23:47
반응형

환경 변수를 지정하고 동일한 명령줄에서 에코할 수 없는 이유는 무엇입니까?

다음 부분을 고려해 보십시오.

$ 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이겁니다.

즉시 옵션은 다음과 같습니다.

  1. SOMEVAR=BBB eval echo zzz '$SOMEVAR' zzz요.
  2. 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가 인터프리터에 대해 다음과 같은 단계를 정의한다는 것입니다.

  1. 파일(Shell 스크립트 참조), -c 호출 옵션에 인수로 제공된 문자열(Bash 호출 참조) 또는 사용자 터미널에서 입력을 읽습니다.
  2. 견적에 설명된 견적 규칙을 준수하여 입력을 단어와 연산자로 나눕니다.이러한 토큰은 메타 문자로 구분됩니다.별칭 확장은 이 단계에서 수행됩니다(별명 참조).
  3. 토큰을 단순 및 복합 명령으로 구문 분석합니다(쉘 명령 참조).
  4. 다양한 셸 확장을 수행하고(Shell Expansions 참조), 확장된 토큰을 파일 이름 목록(파일 이름 확장 참조), 명령 및 인수 목록으로 나눕니다.
  5. 필요한 리디렉션을 수행하고( 리디렉션 참조) 리디렉션 연산자와 해당 피연산자를 인수 목록에서 제거합니다.
  6. 명령을 실행합니다(명령 실행 참조).
  7. 선택적으로 명령이 완료될 때까지 기다렸다가 종료 상태를 수집합니다(종료 상태 참조).

즉, 빌트인은 자체 실행 환경을 구축하지 않기 때문에 수정된 환경을 볼 수 없습니다.또한 간단한 명령(예: /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, 간단한 명령입니다.

  1. 리디렉션은 리디렉션에 설명된 대로 수행해야 합니다.

  2. 각 변수 할당은 값을 할당하기 전에 칠드 확장, 매개 변수 확장, 명령 대체, 산술 확장 및 견적 제거를 위해 확장되어야 합니다.

[...]

명령 이름이 나타나지 않으면 변수 할당이 현재 실행 환경에 영향을 미칩니다.그렇지 않으면 변수 할당은 명령 실행 환경에 대해 내보내야 하며 현재 실행 환경(특수 내장 제외)에 영향을 미치지 않습니다.변수 할당 중 하나가 읽기 전용 변수에 값을 할당하려고 하면 변수 할당 오류가 발생합니다.이러한 오류의 결과는 셸 오류의 결과를 참조하십시오.

따라서: 단순 명령에 대한 접두사 일부에 지정된 할당은 내보내야 하며 호출되는 명령이 특별한 기본 제공 명령이 아닌 한 "현재 셸 환경"에 영향을 미치지 않아야 합니다.또한 이러한 단계는 기본적으로 명령 호출 프로세스에서 늦게 발생하는 리디렉션을 따라야 합니다.


2.12, 셸 실행 환경입니다.

특수 빌트인 이외의 유틸리티(특수 빌트인 유틸리티 참조)는 다음과 같이 구성된 별도의 환경에서 호출해야 합니다.이러한 개체의 초기 값은 아래에 명시된 경우를 제외하고 상위 셸의 값과 동일해야 합니다.

[...]

내보내기 속성이 있는 변수와 명령 기간 동안 명시적으로 내보낸 변수를 함께 유틸리티 환경 변수로 전달해야 합니다.


따라서: 이러한 변수는 포크 후 및 호출되는 명령을 실행하기 전에 하위 셸에 의해 확장되며, 사양에 따라 하위 환경에만 영향을 주어야 합니다.


다른 동작의 경우 다음과 같습니다.

SOMEVAR=BBB sh -c 'echo "$SOMEVAR"'

...의 이점입니다.sh시작할 때 환경 변수에서 셸 변수를 생성하는 인스턴스(POSIX 규격의 섹션 2.5.3에 필요)입니다.


참고로, 요청하신 구문은 하위 셸 내의 할당이 아니라 단순한 명령 내의 할당입니다.파이프라인에 포함된 하위 쉘에서 다음과 같이 할당을 제어할 수 있습니다.

{ SOMEVAR=BBB; echo "$SOMEVAR"; } | somecommand ...

...파이프라인의 첫 번째 구성 요소를 실행하는 하위 쉘에 할당을 넣습니다(쉘이 하위 쉘에서 해당 구성 요소를 실제로 실행하고 있는 경우, POSIX와 관련하여 정의되지 않은 동작). 사양에서 "단, 파이프라인의 일부 또는 모든 명령이 현재 환경에서 실행될 수 있습니다."

그 이유는 이렇게 하면 한 줄에 환경 변수가 설정되기 때문입니다.그렇지만,echo확장이 되지 않습니다.bash따라서 명령이 실행되기 전에 변수가 실제로 확장됩니다.SOME_VAR이에요BBBecho 명령의 컨텍스트에서 사용합니다.

효과를 보려면 다음과 같은 작업을 수행할 수 있습니다.

$ 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 입니다.

반응형