POSIX 쉘의 stdin에서 단일 문자를 읽을 수 있습니까?

POSIX 쉘의 stdin에서 단일 문자를 읽을 수 있습니까?

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 -kor ksh93's read -N1or 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)

관련 정보