read -k를 사용하는 zsh 스크립트를 개발 중입니다. 이와 같은 스크립트를 실행하면( echo a | myscript
) 입력을 받지 못합니다. 분명히 이는 -k가 항상 /dev/tty를 표준 입력으로 사용하기 때문이며, read와 같은 표준 입력을 사용하도록 지시해야 합니다 read -u0
.
그러나 이를 -u0(이전 사례가 작동하도록 함)으로 변경하고 tty를 리디렉션하지 않고 스크립트를 실행하면 스크립트가 중단되고 -u0 없이 했던 것처럼 전혀 실행되지 않습니다. 마찬가지입니다.
편집하다: 디버깅 후 문제는 간단한 것 같습니다. -u0을 사용한 후 -k1 옵션이 더 이상 단일 문자를 읽지 않고 중지됩니다. 이 경우 읽기는 모든 입력을 버퍼링하고 EOL이 도착하자마자 저장하는 것을 제외하고 -k 없이 동일하게 작동합니다.
편집 2: 좀 더 디버깅한 후에 이것이 -u0과 작동하지 않는 원시 모드와 관련이 있다는 것을 알았습니다. 읽기 전에 stty raw/cooked를 추가하면 작동하지만(입력 키 입력을 처리하기 위해 \n 대신 \r을 사용하는 경우는 제외), tty가 아닌 stdin을 사용하여 실행하면 작동이 중단됩니다.
두 모드를 모두 호환되게 만드는 방법이 있나요?
사실, 스크립트가 완전히 다르게 동작하는 이유를 이해하고 싶습니다. fd0은 -u0을 사용하여 읽든 안 읽든 기본적으로 /dev/tty와 동일합니다.
답변1
read -k
두 가지 작동 모드가 있습니다: (N 문자 읽기) 및 read -q
(읽기 y
또는 ):n
- 기본적으로 터미널에서 읽습니다. 그들은 한 줄씩 읽는 대신 바이트 단위로 읽기(필요한 만큼의 문자 읽기)를 위해 터미널을 원시 모드로 설정합니다.
- 기존 파일 설명자(
-u
숫자 또는-p
현재 코프로세스와 통신하는 데 사용되는 파이프)에서 읽도록 지시할 수 있습니다. 이 경우 파일 설명자에서 읽기만 합니다.
zsh에게 특정 소스에서 읽도록 지시하는 옵션은 없지만 터미널에서 읽는 경우 터미널 모드를 변경하세요. 하지만 직접 구성할 수 있습니다. 표준 입력이 터미널인지 확인하고 -u0
터미널인 경우 전달하지 마세요.
if [[ -t 0 ]]; then
read -k1 …
else
read -k1 -u0 …
fi