tty 출력과 함께 가변 명령 파이프 stdin 및 stdout을 사용할 때 zsh가 터미널에 입력하지 못합니다.

tty 출력과 함께 가변 명령 파이프 stdin 및 stdout을 사용할 때 zsh가 터미널에 입력하지 못합니다.

시스템 메시지:

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.


내가보고 있어요fzf키바인딩bash그리고zsh.

그들 모두가 어떻게 변수 명령을 실행하는지 주목하세요 $(__fzfcmd). __fzfcmd기본적으로 출력은 fzfstdout으로 이루어지며 인수 대체는 fzf결과를 출력하는 command()만 실행합니다.

bash스크립트와 스크립트의 한 가지 차이점 zsh은 스크립트가 bash출력을 추가로 파이프 $(__fzfcmd)하지만 zsh이를 배열로 캡처한다는 것입니다. 내 생각엔 zsh입력할 수 없는 추가 파이프 출력과 파이프하는 프로세스가 표준 입력을 얻지 못할 때 문제가 발생하기 때문인 것 같습니다. 유일한 옵션은 또는입니다. 왠지 백그라운드에서 프로세스가 처리되고 있는 것 같습니다. 아니면 그냥 배열에 넣어서 사용할 수도 있습니다.fzffzffzf^Z^C^Czle 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)대신 프로세스 교체를 사용 하도록 리디렉션하는 파일로 리디렉션합니다 .stdoutstinstdin

답변1

귀하의 문제는 귀하의 확장 기능을 잘못 인용한 것으로 요약됩니다.

에서 인용zsh:14 확장

$(...)괄호로 묶이고 달러 기호(예: )가 앞에 오거나 악센트 문자(예: ' ')로 인용된 명령은 ...표준 출력을 대체하고 후행 개행 문자를 제거합니다. 대체 항목을 큰따옴표로 묶지 않으면 IFS 매개변수를 사용하여 출력을 단어로 나눕니다. 대체품은 $(cat foo)동일하지만 더 빠른 대체품으로 대체될 수 있습니다 $(<foo). 두 경우 모두 GLOB_SUBST 옵션이 설정되면 출력은 파일 이름 생성에 따릅니다.

질문의 예제 #2는 다음과 같은 이유로 무한한 NULL 에코를 발생시킵니다.

대체 항목을 큰따옴표로 묶지 않으면 IFS 매개변수를 사용하여 출력을 단어로 나눕니다.

즉, echo기본 구분 기호가 SPACE이므로 쉘은 무기한 대기하므로 echo는 완료되지 않습니다. TLDP: 내부 변수를 참조하세요.. 이로 인해 cat명령에 대한 행잉 파이프가 남습니다.

직관적으로 나는 출력 리디렉션으로 인해 4와 5가 작동한다고 믿습니다.

관련 정보