![tty 출력과 함께 가변 명령 파이프 stdin 및 stdout을 사용할 때 zsh가 터미널에 입력하지 못합니다.](https://linux55.com/image/123941/tty%20%EC%B6%9C%EB%A0%A5%EA%B3%BC%20%ED%95%A8%EA%BB%98%20%EA%B0%80%EB%B3%80%20%EB%AA%85%EB%A0%B9%20%ED%8C%8C%EC%9D%B4%ED%94%84%20stdin%20%EB%B0%8F%20stdout%EC%9D%84%20%EC%82%AC%EC%9A%A9%ED%95%A0%20%EB%95%8C%20zsh%EA%B0%80%20%ED%84%B0%EB%AF%B8%EB%84%90%EC%97%90%20%EC%9E%85%EB%A0%A5%ED%95%98%EC%A7%80%20%EB%AA%BB%ED%95%A9%EB%8B%88%EB%8B%A4..png)
시스템 메시지:
macOS Sierra 10.12.6
zsh 5.4.2 (x86_64-apple-darwin16.7.0)
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
스크롤예제가 만든 단순화된 예를 자세히 알아보고 싶다면 맨 아래에 있습니다.
참고: 저는 큰 사용자가 아닙니다 zsh
.
그들 모두가 어떻게 변수 명령을 실행하는지 주목하세요 $(__fzfcmd)
. __fzfcmd
기본적으로 출력은 fzf
stdout으로 이루어지며 인수 대체는 fzf
결과를 출력하는 command()만 실행합니다.
bash
스크립트와 스크립트의 한 가지 차이점 zsh
은 스크립트가 bash
출력을 추가로 파이프 $(__fzfcmd)
하지만 zsh
이를 배열로 캡처한다는 것입니다. 내 생각엔 zsh
입력할 수 없는 추가 파이프 출력과 파이프하는 프로세스가 표준 입력을 얻지 못할 때 문제가 발생하기 때문인 것 같습니다. 유일한 옵션은 또는입니다. 왠지 백그라운드에서 프로세스가 처리되고 있는 것 같습니다. 아니면 그냥 배열에 넣어서 사용할 수도 있습니다.fzf
fzf
fzf
^Z
^C
^C
zle vi-fetch-history
그것에 달려. 이 bash
버전은 키 바인딩에 대한 일부 작업을 수행합니다."\e^": history-expand-line
지금은 중요하지 않습니다 fzf
. tty
이 문제를 일으키려면 매개변수 대체에 의해 호출된 프로그램 에 대한 출력만 필요한 것 같습니다 . 그래서 좀 더 간단한 예를 보여드리겠습니다.
tty
이 문제를 일으킬 수 있는 다른 명령 의 출력은 다음과 같습니다 zsh
.
- 독사(파이프라인 중간에 편집기를 실행합니다)
'vim -'
(vim을 stdin에서 읽습니다. vipe와 유사하지만 stdout으로 출력하지 않습니다)
아래 예에서 vipe
별도의 설치를 수행하지 않으려면 모든 항목을 다음으로 바꾸십시오. 편집기 내용은 그런 표준 출력으로 출력되지 vim -
않습니다 .vim -
vipe
예:
1) echo 1 | vipe | cat # works in both bash and zsh
2) echo 1 | $(echo vipe) | cat # works in bash only. zsh problem with no output until I hit `^C`:
^C
zsh: done echo 1 |
zsh: suspended (tty output) $(echo vipe) |
zsh: interrupt cat
# seems like the process is backgrounded. I can still see it in jobs command
3) cat <(echo 1 | $(echo vipe)) # zsh and bash has the problem. I'm guessing because
# the file isn't finished writing and cat is
# blocking vipe's tty output
# both their `^C` output is just:
^C # nothing special, as expected
4) cat < <(echo 1 | $(echo vipe)) # works in both bash and zsh
5) echo 1 | $(echo vipe) > >(cat) # works in both bash and zsh
# The following don't have and input pipe to vipe.
# Type something then send EOF with ^D
6) vipe | cat # works for both
7) $(echo vipe) | cat # works for both
2)
이제 주로 문제가 발생한 이유 zsh
는 무엇인지 bash
, 왜 문제가 4)
해결되었는지 알고 싶습니다 .5)
zsh
이 질문에 대한 요구 사항은 zsh
제가 제목에 넣은 것과 정확히 같습니다.
- 입력관
tty
출력으로 변수/인수 대체에 의해 실행되는 명령- 출력관
고쳐 쓰다
zsh
이 문제를 일으키지 않는 또 다른 해결 방법을 추가했습니다 5)
. 비슷 하지만 직접 리디렉션하는 4)
대신 프로세스 교체를 사용 하도록 리디렉션하는 파일로 리디렉션합니다 .stdout
stin
stdin
답변1
귀하의 문제는 귀하의 확장 기능을 잘못 인용한 것으로 요약됩니다.
에서 인용zsh:14 확장
$(...)
괄호로 묶이고 달러 기호(예: )가 앞에 오거나 악센트 문자(예: ' ')로 인용된 명령은...
표준 출력을 대체하고 후행 개행 문자를 제거합니다. 대체 항목을 큰따옴표로 묶지 않으면 IFS 매개변수를 사용하여 출력을 단어로 나눕니다. 대체품은$(cat foo)
동일하지만 더 빠른 대체품으로 대체될 수 있습니다$(<foo)
. 두 경우 모두 GLOB_SUBST 옵션이 설정되면 출력은 파일 이름 생성에 따릅니다.
질문의 예제 #2는 다음과 같은 이유로 무한한 NULL 에코를 발생시킵니다.
대체 항목을 큰따옴표로 묶지 않으면 IFS 매개변수를 사용하여 출력을 단어로 나눕니다.
즉, echo
기본 구분 기호가 SPACE이므로 쉘은 무기한 대기하므로 echo는 완료되지 않습니다. TLDP: 내부 변수를 참조하세요.. 이로 인해 cat
명령에 대한 행잉 파이프가 남습니다.
직관적으로 나는 출력 리디렉션으로 인해 4와 5가 작동한다고 믿습니다.