“A = 10 echo $ A”가 10을 인쇄하지 않는 이유는 무엇입니까?


25

이 명령은

A=10 echo $A

빈 줄을 인쇄합니다. 왜 안돼 10? 전체 임시 환경 설정이 작동하지 않는 이유는 무엇입니까?

해결책보다는 이유와 설명을 알고 싶습니다.

나는 사용했다

LANG=C gcc ...

gcc가 시스템 언어 (중국어) 대신 대체 언어 (영어)를 사용하도록합니다. 그래서 VAR=value접두사가 그 뒤에 오는 명령에 대한 임시 환경을 설정 한다고 가정 합니다. 그러나 오해가있는 것 같습니다.

답변:


22

명령 평가의 여러 단계가 수행되는 순서는 중요합니다.

A=10 echo $A제 파싱 세 단어로 이루어진 간단한 명령에 대한 명령 A=10, echo$A. 그런 다음 각 단어에는 변수 대체가 적용됩니다. 즉 변수 확장을 $A값 으로 변환하는 것 (표시되지 않는 단계는 생략)입니다.

경우 A값을 가지고 foo초기 확장 단계의 결과는 여전히 세 단어를 가지고 간단한 명령은 다음과 같습니다 A=10, echo그리고 foo. 쉘은이 시점에서 처음에 따옴표 안에 있던 문자를 기억합니다 (이 경우에는 없음). 다음 단계는 명령을 실행하는 것입니다. 이후 A=10등호 따르는 유효한 변수 이름으로 시작되고, 이것은 과제로 처리되고; 변수 A10명령 실행 중에 쉘과 환경 모두에 설정됩니다 . (일반적으로 당신은 쓸 필요가 export A가지고 A단지 쉘 변수와 환경이 아니라, 이것은 예외입니다.) 다음 단어가 할당되지 않습니다, 그것은 명령 이름 (그것의 내장 명령)으로 처리 그래서. 그만큼echo명령은 변수에 의존하지 않으므로 A=10 echo $A와 정확히 동일한 효과가 echo $A있습니다.

명령 기간 동안 만 변수를 설정하지만 명령을 실행하는 동안 할당을 고려하려는 경우 서브 쉘을 사용할 수 있습니다. 괄호로 표시된 서브 쉘은 모든 상태 변경 (변수 지정, 현재 디렉토리, 함수 정의 등)을 서브 쉘에 로컬로 만듭니다.

(A=10; echo $A)

export A=10외부 프로그램에서 볼 수 있도록 변수를 환경으로 내보내려면 확인하십시오 .


고마워, 내가 말하고 A=10 (echo $A)얻을 수 10있습니까?
어스 엔진

2
@EarthEngine 아니요, 구문 오류입니다. 할당은 간단한 명령의 시작 부분에 있어야합니다 (예 : 명령 이름 및 일부 매개 변수, 선택적으로 일부 초기 지정 및 일부 재 지정). 스크립트의 나머지 부분 에도 A=10; (echo $A)출력 10을 설정 A합니다.
Gilles 'SO- 악마 그만해'

2
@EarthEngine하지만 말할 수 있습니다 A=10 eval 'echo $A'. 작은 따옴표 $A는 전체 줄이 평가 될 때까지 해석을 중지합니다 . 나는이 대답이 수용 된 것보다 더 옳다고 생각합니다.
Oli

이것이 올바른 설명이라고 생각합니다. 동작의 이유는 확장 $A및 할당 A이 발생 하는 순서입니다 . 예를 들어 A=5; A=6 let 'a=A'; echo $a반환 6하지 않으며 내장 명령이기 때문에 서브 쉘을 시작 5하지 않는다고 생각 let합니다.
David Ongaro

@EarthEngine : 올바른 설명이 있다고 말했다 때 위해 평가, 그것은 오해의 소지가있을 수 있습니다 A=10 echo $A없는 설정 A=10이후 모든 명령에 대해 서로 다른 라인 (할당이 때 분명히에있는 경우에도 이미 평가). 그것은 주문에 관한 것이 아니라 범위
MestreLion

37

당신이 사용하는 경우 LANG=C gcc ... 어떤 일이 쉘에 대한 LANG을 설정이다 gcc의 환경 에서만 , 그리고 하지 에 대한 현재의 환경 자체 ( 참고 참조 ). 따라서 gcc완료 후 LANG이전 값으로 돌아갑니다 (또는 설정되지 않음).

또한, 사용 A=10 echo $A하는 경우 에코가 아닌 $ A를 대체 하는 이고,이 대체 ( "확장"이라고 함) 는 명령문이 평가 되기 전에 (할당 포함 ) 발생 하므로 예상 A값 으로 작동 하려면 이미 설정되어 있어야합니다. 그 진술 이전 의 현재 환경 에서 .

그것이 A=10 echo $A예상대로 작동하지 않는 이유입니다 : A=10echo에 대해 설정되지만 echo는 환경 변수의 값을 내부적으로 무시합니다 A. 그리고 현재 쉘에$A 설정된 값 (없음) 으로 바뀐 다음 에코에 대한 인수로 전달됩니다.

당신의 가정이 정확 그래서 : VAR=value command 수행 작업을하지만,이 경우에만 관련이 command내부적으로 사용하는 VAR를. 그렇지 않으면에 value대한 인수 로 여전히 전달할 수 command있지만 인수는 현재 쉘로 대체 되므로 사용 전에 설정해야합니다.VAR=value; command "$VAR"

실행 가능 스크립트를 작성하는 방법을 알고 있으면 다음과 같이 테스트 해보십시오.

#!/bin/sh
echo "1st argument is $1"
echo "A is $A"

다른 이름으로 저장 testscript하고 시도하십시오.

$ A=5; A=10 testscript "$A"; echo "$A"
1st argument is 5
A is 10
5

마지막으로 환경 변수와 프로그램 인수 의 차이점을 아는 것이 좋습니다.

다음은 좋은 참고 자료입니다.

.

(*) 참고 : 기술적으로 쉘이 않는 일부 명령, 같은 : 왜 여기에 너무 현재의 환경에서 설정하고,이다 echo, read하고 test있는 쉘 내장 명령이 , 그리고 같은 그들은 자식 프로세스를 생성하지 않습니다. 현재 환경에서 실행됩니다. 그러나 셸은 명령이 실행될 때까지만 할당을 처리하므로 모든 실제적인 목적에 따라 효과는 동일합니다. 할당은 단일 명령으로 만 볼 수 있습니다.


2
이 설명은 실제로는 정확하지 않지만 몇 가지 경우를 제외하고는 모두 올바른 결론을 내립니다. 실제 설명은 확장 순서입니다 $A. 과제가 수행되기 전에 평가됩니다. 변수의 값에 따라 동작하는 일반 내장 유틸리티의 경우에만 설명이 실패한다고 생각합니다. 내장에는 지정된 값이 표시됩니다. 일반적인 예는 IFS=: read one two three rest콜론으로 구분 된 필드를 읽는 것 read입니다 IFS. 내장은의 값을 봅니다.
Gilles 'SO- 악마 그만해'

"현재 쉘 자체가 아님"이 잘못되었습니다. 변수가 현재 쉘에 설정되어 있지만 현재 간단한 명령에 대해서만 지속됩니다. 관심이 있다면에 echo대한 값 10을 볼 수 있습니다 A.
Gilles 'SO- 악마 그만

@Gilles : 설명을 해주셔서 감사합니다! 나는이 미묘함을 몰랐다. 따라서 내가 올바르게 이해했다면 bash 현재 환경에 대해 설정해야 합니다. 그렇지 않으면 내장 (new을 생성하지 않음 pid)은 다른 "regurlar"명령과 같이 할당을 볼 수 없습니다. 그러나 할당 범위를 제한하기 위해 명령이 완료된 후 설정이 해제 됩니다. 이것이 맞습니까? 그에 따라 답변을 수정하겠습니다. PS : 교칙 옆으로, 나는 아직도 다른 사람이 생각할 수있는, 답변이 범위 측면하지 평가 순서에 강조해야한다고 생각 A=10 test; echo $A(10) 인쇄합니다
MestreLion

3

분명히 원하는 것을 수행하는 한 가지 확실한 방법은 명령을 실행하는 것입니다.

A=10 eval 'echo $A'

실제로 값 10을 $ A 대신 나중에 컨텍스트로 대체하는 것을 연기합니다 (즉, 할당에 대해 이미 알고있는 eval의 '내부'). 작은 따옴표는 필수입니다. 이러한 구문은 현재 환경을 오염시킬 위험없이 원하는 명령 (이 경우 에코)에 할당을 명확하게 전달합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.