리디렉션 후 $ 확장이 예상대로 수행되지 않습니다.

리디렉션 후 $ 확장이 예상대로 수행되지 않습니다.

자식 프로세스에서 변수 및 산술 확장을 수행할 것으로 bash보입니다 .zsh

a) , 또는 같은 리디렉션 연산자를 따릅니다 <.>>><<<

b) 그들이 속한 명령은 내장된 명령이나 기능이 아닙니다.

bash -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
0
zsh -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
0

ksh -c 'i=0; /bin/echo > $((i=7)).txt; echo $i'
7

kshbash위 내용은 or 를 제외한 다른 쉘과 동일합니다 zsh.

이는 산술 확장과는 아무런 관련이 없습니다. 마찬가지로, 같은 일이 발생합니다.

unset i; /bin/echo >${i:=7}.txt; echo $i

또는 7이외의 쉘에서만 인쇄 됩니다.bashzsh

bash그러나 그것이 충분히 나쁘지 않은 것처럼 및 사이의 동작은 이해할 수 있는 방식으로 일관성이 없습니다 zsh.

bash -c 'i=0; command echo > $((i++)).txt; echo $i'
1
zsh -c 'i=0; command echo > $((i++)).txt; echo $i'
0

bash -c 'i=0; i=$i /usr/bin/printenv i > $((++i)).bash; echo $i; cat *.bash'
0
0
zsh -c 'i=0; i=$i /usr/bin/printenv i > $((++i)).zsh; echo $i; cat *.zsh'
0
1

그래서 내 질문은 다음과 같습니다.표준은 무엇을 말합니까?이것이 허용됩니까?

KEY=val cmd변수 할당에 대해 "현재 실행 환경에 영향을 미칠 수 있는지 여부" 와 같은 많은 정보를 찾을 수 있었지만 $리디렉션, 확장 및 외부 명령 간의 상호 작용에 대해서는 찾을 수 없었습니다.

그리고 -expansions의 일부로 수행된 변수 할당에도 적용될 가능성은 거의 없습니다 . 왜냐하면 $외부 또는 내장 여부에 관계없이 ls $((i=2+3))모든 쉘에서 i로 설정되기 때문입니다.5ls

답변1

이는 지정되지 않았으므로 각 쉘은 세부 사항을 기록하지 않고도 원하는 작업을 수행할 수 있습니다. (역사적인 관점에서 볼 때, 다른 껍질은 다른 일을 하기 때문에 지정되지 않았습니다.) 기술적으로 껍질은 동전을 던질 수 있습니다. 실제로 별도의 환경에서 실행되는 것과 실행되지 않는 것에 대한 세부 사항은 경우에 따라 수행되는 최적화에 따라 달라질 수 있습니다. 명령이 내장되어 있는지 여부에 따라 리디렉션이 to/from인지 여부 /dev/null에 따라 달라집니다. set -e유효한지 여부, 명령이 목록의 마지막 명령인지 여부 등에 따라 트랩이 활성화됩니다.

~에서SUSv4(POSIX.1-2008) “셸 및 유틸리티” — §2.9.1 “간단한 명령”:

명령 이름이 특수 내장 유틸리티 또는 함수가 아닌 경우 명령 실행 환경에 대해 변수 할당을 내보내야 하며 4단계에서 수행된 확장의 부작용을 제외하고 현재 실행 환경에 영향을 주어서는 안 됩니다. 이 경우 지정되지 않았습니다.

  • 4단계의 후속 확장에 할당이 표시됩니까?

  • 이러한 확장의 부작용으로 수행된 변수 할당은 4단계의 후속 확장이나 현재 쉘 실행 환경 또는 둘 다에서 볼 수 있습니다.

명확하게 말하면 "4단계"에는 매개변수 확장(예: ${i:=7}) 및 산술 확장(예: $((i=7)))이 포함됩니다. "현재 실행 환경에 영향을 주지 않아야 하는" 변수 확장은 명령 앞에 오는 것입니다 i=7 ls. 따라서 무엇보다도 이 단락에서는 매개변수 확장이나 변수 확장이 변수 값을 수정하는 경우 명령이 반환된 후에 이것이 영향을 미칠지 여부가 지정되지 않는다고 명시합니다.

실제로 쉘은 일반적으로 먼저 하위 쉘에서 리디렉션을 분기하고 수행하여 외부 명령에 리디렉션을 적용합니다. 그러나 서브셸을 생성하기 전이나 후에 리디렉션을 대상으로 하는지 여부가 다릅니다.

관련 정보