명령의 출력을 셸의 내장 함수로 파이프하려고 하는데 read
동작이 달라집니다.zsh
bash
$ bash -c 'echo hello | read test; echo $test'
$ zsh -c 'echo hello | read test; echo $test'
hello
이 방법은 에서는 작동하지 않지만 bash
다음 방법은 두 가지 모두에 작동합니다.
$ bash -c 'echo hello | while read test; do echo $test; done'
hello
$ zsh -c 'echo hello | while read test; do echo $test; done'
hello
왜 그런 겁니까? 제가 잘못 사용한 걸까요 read
? 나는 이것을 스크립트에서 사용하는 것이 test="$(echo hello)"
참조 문제를 더 주의 깊게 다루도록 강요하는 것보다 더 읽기 쉽다는 것을 알았습니다.
답변1
POSIX를 사용하여 표준화되지 않은 결과를 관찰하고 있습니다.
POSIX는 인터프리터가 파이프라인을 실행하는 방식을 표준화하지 않습니다.
유명한 Bourne Shell의 경우 파이프라인의 가장 오른쪽 프로그램은 메인 쉘의 서브루틴도 아닙니다. 그 이유는 이 구현이 느리지만 코드가 거의 필요하지 않기 때문입니다. 이는 메모리가 64kB만 있는 경우 중요합니다. 이 변형에서는 read
명령이 하위 프로세스에서 실행되므로 하위 프로세스에 할당된 셸 변수는 기본 셸에 표시되지 않습니다.
ksh
또는 (가장 최근에는 Bourne Shell)과 같은 최신 쉘은 bosh
파이프의 모든 프로세스가 기본 쉘의 직접적인 하위 항목이 되는 방식으로 파이프를 생성하며, 가장 오른쪽 프로그램이 내장 쉘인 경우 기본 쉘에 의해 실행되기도 합니다. 껍데기.
이 모든 것은 read
프로그램이 메인 쉘의 쉘 변수를 수정하도록 허용하는 데 필요합니다. 따라서 이 변형(가장 빠른)에서만 기본 셸에서 변수 할당 결과를 볼 수 있습니다.
두 번째 예에서는 전체 while
루프가 동일한 하위 프로세스에서 실행되므로 수정된 버전의 셸 변수를 인쇄할 수 있습니다.
현재 파이프된 명령에 0이 아닌 종료 코드가 있는지 여부에 대한 정보를 얻기 위해 POSIX 셸에 대한 지원을 추가하라는 요청이 있습니다. 이를 달성하려면 파이프라인의 모든 프로그램이 메인 셸의 직접적인 서브루틴이 되는 방식으로 셸을 구현해야 합니다. 허용되는 수준에 가깝습니다.
echo foo | read val; echo $val
예상된 작업이 수행되고 그 시점부터 기본 셸에서 읽기를 실행하기 위한 요구 사항만 누락됩니다.