program story

Bash : 명령 줄에서 에코에 대한 환경 변수 지정?

inputbox 2020. 10. 5. 07:54
반응형

Bash : 명령 줄에서 에코에 대한 환경 변수 지정?


이 스 니펫을 고려하십시오.

$ SOMEVAR=AAA
$ echo zzz $SOMEVAR zzz
zzz AAA zzz

여기에 내가 설정 한 $SOMEVARAAA첫 번째 줄에 - 나는 두 번째 줄에 에코 때, 나는 도착 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. 환경에 설정된 후에 만 ​​평가됩니다 (단일 명령 기간 동안 일시적으로).

또 다른 옵션은 하위 쉘 표기법을 사용하는 것입니다 ( 마커스 쿤답변 에서 제안한 것처럼 ).

(SOMEVAR=BBB; echo zzz $SOMEVAR zzz)

변수는 하위 쉘에서만 설정됩니다.


재검토 된 문제

솔직히, 매뉴얼은이 점에서 혼란 스럽습니다. GNU 배쉬 설명서는 말한다 :

간단한 명령이나 함수 [내장을 제외 함]에 대한 환경은 쉘 매개 변수에 설명 된대로 매개 변수 지정을 접 두부로 추가하여 일시적으로 보강 할 수 있습니다. 이러한 할당 명령문은 해당 명령이 표시하는 환경에만 영향을줍니다.

실제로 문장을 구문 분석하면 명령 / 함수에 대한 환경 은 수정되지만 상위 프로세스의 환경은 수정되지 않습니다. 따라서 이것은 작동합니다.

$ 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. 파일 (셸 스크립트 참조), -c 호출 옵션에 대한 인수로 제공된 문자열 (Bash 호출 참조) 또는 사용자 터미널에서 입력을 읽습니다.
  2. Quoting에 설명 된 인용 규칙에 따라 입력을 단어와 연산자로 나눕니다. 이러한 토큰은 메타 문자로 구분됩니다. 별칭 확장은이 단계에서 수행됩니다 (별칭 참조).
  3. 토큰을 단순 및 복합 명령으로 구문 분석합니다 (셸 명령 참조).
  4. 다양한 셸 확장 (셸 확장 참조)을 수행하여 확장 된 토큰을 파일 이름 목록 (파일 이름 확장 참조)과 명령 및 인수로 나눕니다.
  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 )

이유:

  • 다음 명령에서 세미콜론 또는 새 줄로 할당을 분리해야합니다. 그렇지 않으면 다음 명령 (echo)에 대한 매개 변수 확장이 발생 하기 전에 실행되지 않습니다 .

  • 현재 행을 넘어 지속되지 않도록 서브 쉘 환경 내에서 할당 해야합니다.

이 솔루션은 다른 솔루션이 제안한 것보다 더 짧고 깔끔하며 효율적이며 특히 새로운 프로세스를 생성하지 않습니다.


The reason is that this sets an environment variable for one line. But, echo does not do the expansion, bash does. Hence, your variable is actually expanded before the command is executed, even though SOME_VAR is BBB in the context of the echo command.

To see the effect, you can do something like:

$ SOME_VAR=BBB bash -c 'echo $SOME_VAR'
BBB

Here the variable is not expanded until the child process executes, so you see the updated value. if you check SOME_VARIABLE again in the parent shell, it's still AAA, as expected.


SOMEVAR=BBB; echo zzz $SOMEVAR zzz

Use a ; to separate statements that are on the same line.


Here's one alternative:

SOMEVAR=BBB && echo zzz $SOMEVAR zzz

참고URL : https://stackoverflow.com/questions/10938483/bash-specifying-environment-variables-for-echo-on-command-line

반응형