read -r
그건 그저POSIX에 의해 지정됨; 문자 read -n NUM
읽기에는 NUM
적합하지 않습니다. stdin에서 주어진 수의 문자를 읽은 후 자동으로 반환하는 이식 가능한 방법이 있습니까?
내 사용 사례는 다음 프롬프트를 인쇄하는 것입니다.
Do the thing? [y/n]
y
가능하다면 입력 후 또는 n
사용자가 Enter 키를 누르지 않고도 자동으로 프로그램이 계속되도록 하고 싶습니다 .
답변1
문자를 읽는다는 것은 완전한 문자를 얻을 때까지 한 번에 한 바이트씩 읽는 것을 의미합니다.
POSIX 도구 상자를 사용하여 바이트를 읽으려면 dd bs=1 count=1
.
그러나 장치가 icanon
모드에 있을 때(일반적으로 기본값) 터미널 장치에서 데이터를 읽는 것은 Return(일명 Enter)을 누를 때만 반환됩니다. 왜냐하면 그 전에 터미널 장치 드라이버는 다음을 수행할 수 있는 A 라인 편집기 양식을 구현하기 때문입니다. 또는 기타 편집 문자를 사용하여 입력한 내용을 수정하고, Backspace입력한 내용은 편집 중인 행을 제출할 때만( 또는 + 사용) 읽기 응용 프로그램에서 사용할 수 있게 됩니다.ReturnCtrlD
따라서 ksh
's read -n/N
또는 zsh
's read -k
는 stdin이 터미널 장치임을 감지하면 장치를 해당 모드에서 꺼내어 icanon
터미널이 전송된 바이트를 읽을 수 있도록 합니다.
이제 이 내용은 다음 ksh
과 같습니다.read -n n
위로n
캐릭터 에한 줄에서, 개행 문자를 읽을 때( 문자 -N n
읽기 용 n
) 여전히 중지됩니다. bash
, ksh93과 달리 -n
및 에 대한 IFS 및 백슬래시 처리를 계속 수행합니다 -N
.
Mimics zsh
's read -k
or ksh93
's read -N1
or bash
's IFS= read -rN 1
, 즉 POSIXly에서 stdin에서 하나의 문자만 읽는 것입니다.
readc() { # arg: <variable-name>
if [ -t 0 ]; then
# if stdin is a tty device, put it out of icanon, set min and
# time to sane value, but don't otherwise touch other input or
# or local settings (echo, isig, icrnl...). Take a backup of the
# previous settings beforehand.
saved_tty_settings=$(stty -g)
stty -icanon min 1 time 0
fi
eval "$1="
while
# read one byte, using a work around for the fact that command
# substitution strips trailing newline characters.
c=$(dd bs=1 count=1 2> /dev/null; echo .)
c=${c%.}
# break out of the loop on empty input (eof) or if a full character
# has been accumulated in the output variable (using "wc -m" to count
# the number of characters).
[ -n "$c" ] &&
eval "$1=\${$1}"'$c
[ "$(($(printf %s "${'"$1"'}" | wc -m)))" -eq 0 ]'; do
continue
done
if [ -t 0 ]; then
# restore settings saved earlier if stdin is a tty device.
stty "$saved_tty_settings"
fi
}
답변2
에서 인용이 답변...이것은 bash에서 작동합니다.
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
답변3
dd에 대한 다른 솔루션:
key=$(stty -icanon; dd ibs=1 count=1 2>/dev/null)