변수를 명령 접두어로 사용하여 환경 변수를 설정할 수 없는 이유는 무엇입니까?

변수를 명령 접두어로 사용하여 환경 변수를 설정할 수 없는 이유는 무엇입니까?

일반적으로 다음과 같은 접두사를 추가하여 명령에 대한 환경 변수를 설정할 수 있습니다.

hello=hi bash -c 'echo $hello'

또한 변수를 사용하여 다음과 같이 명령 호출의 일부를 대체할 수 있다는 것도 알고 있습니다.

$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"

변수를 명령 접두사로 사용하여 환경 변수를 설정할 수 없다는 사실에 매우 놀랐습니다. 테스트 사례:

$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found

변수를 사용하여 환경 변수를 설정할 수 없는 이유는 무엇입니까? 접두사 부분은 특별한 부분인가요? eval을 미리 사용하여 작동하게 할 수 있지만 여전히 이유를 이해하지 못합니다. 나는 bash 4.4를 사용하고 있습니다.

답변1

나는 이것이 당신에게 매력적인 순서의 일부라고 생각합니다.

변수 할당이나 리디렉션이 아닌 단어는 확장됩니다(셸 확장 참조). 확장 후에도 여전히 단어가 있는 경우 첫 번째 단어는 명령 이름으로 처리되고 나머지 단어는 인수로 처리됩니다.

그게 출신이야배쉬 참조 매뉴얼단순 명령 확장 섹션에서.

이 예 에서는 cmd=bash환경 변수가 설정되지 않았으며 bash는 매개변수 확장을 통해 명령줄을 처리하고 bash -c "echo hi".

prefix=hello=hi예에서는 다시 첫 번째 패스에 변수 할당이 없으므로 매개변수 확장으로 처리가 계속되어 첫 번째 단어가 생성됩니다 hello=hi.

변수 할당이 처리되면 명령 실행 중에 다시 처리되지 않습니다.

아래에서 처리 및 결과를 확인하세요 set -x.

$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42

"환경 변수"의 보다 안전한 변형인 "변수 확장"의 경우 eval다음을 고려하십시오.비잔드리아의 조언env:

prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi

엄밀히 말하면 유틸리티의 주요 기능을 사용하여 명령에 환경 변수를 할당하므로 이는 명령줄 변수 할당이 아니지만 env동일한 목표를 달성합니다. 변수는 $prefix명령줄 처리 중에 확장되어 name=value를 제공 env한 다음 에 전달됩니다 bash.

답변2

왜냐하면 $prefix이것은 작업이 아니기 때문입니다.@Jeff는 더 긴 설명을 가지고 있습니다.

함수를 사용하여 비슷한 작업을 수행할 수 있습니다.

$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi

...원하는 경우 쌓을 수도 있습니다.

$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123

관련 정보