오른쪽 화살표 키를 누르는 bashscript 감지합니까? stty_state=`stty -g` stty raw; stty

키 코드가 오른쪽 화살표 키가 아니더라도 왜 항상 참으로 감지합니까?

stty_state=`stty -g`
stty raw; stty -echo
keycode=`dd bs=1 count=1 2>/dev/null`
stty "$stty_state"

echo $keycode

if [ "$keycode"=39 ]; then
echo "Right Arrow Key Pressed!"
fi


답변

아마 2+ 바이트 중 첫 번째를 읽습니다. $keycode화살표 키를 누르면 스크립트에서 ESC가됩니다.

화살표 키는 다음과 같습니다.

\x1b + some value

조건식에 공백이 없기 때문에 항상 true로 평가됩니다.

편집 : 해당 진술에 대한 업데이트.

귀하 if[명령 의 종료 상태에서 작동합니다 . [명령은 동일합니다 test. 그것이 명령 이라는 사실은 매우 중요한 사실입니다. 명령으로 인수 사이에 공백이 필요합니다. 이 [명령은 ]마지막 인수로 필요하다는 점에서 더욱 특별 합니다.

[ EXPRESSION ]

EXPRESSION에 의해 ​​결정된 상태로 명령이 종료됩니다. 1 또는 0, 또는 거짓 .

괄호를 작성하는 이국적인 방법 은 아닙니다 . 다시 말해 C와 같이 구문의 일부 가 아닙니다if .

if (x == 39)

으로:

if [ "$keycode"=39 ]; then

당신은 발행합니다 :

[ "$keycode"=39 ]

어느쪽으로 확장

[ \x1b=39 ]

여기서 하나의 인수 \x1b=39로 읽습니다 . 때 또는 주어진 하나 개의 인수가 거짓으로 종료 하는 경우에만 EXPRESSION가 null – 결코 될 것 없다된다. 비어 있더라도 결과는 (널 / 빈이 아님)입니다.test[$keycode=39

그것을 보는 또 다른 방법은 당신이 말하는 것입니다.

if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.

이러한 질문에 대한 답변 자세한 내용은 읽기 -에뿐만 아니라 토론 [대를 [[:

그런 점에서 진드기를 다시 연구 할 수 있습니다. $( )


화살표 키를 사용한 멀티 바이트 이스케이프 시퀀스 :

상단에서 언급했듯이 : 아마도 2+ 바이트 중 첫 번째를 읽습니다. $keycode화살표 키를 누르면 스크립트에서 ESC가됩니다.

화살표 및 기타 특수 키 를 사용하면 시스템으로 이스케이프 시퀀스 가 전송됩니다. ESC의 바이트 신호는 “여기 다르게 해석되어야 일부 바이트 온다” . 아스키 것 화살표 키에 관해서는 [ASCII 다음 A, B, C또는 D.

즉, 화살표 키를 다룰 때 3 바이트를 구문 분석해야합니다.

이 방향으로 무언가를 시도하여 확인할 수 있습니다.

{   stty_state=$(stty -g)
    stty raw isig -echo
    keycode=$(dd bs=8 conv=sync count=1)
    stty "$stty_state"
} </dev/tty 2>/dev/null
printf %s "$keycode" | xxd

수율:

HEX        ASCII
1b 5b 41   .[A # Up arrow
1b 5b 42   .[B # Down arrow
1b 5b 43   .[C # Right arrow
1b 5b 44   .[D # Left arrow
 |  |  |
 |  |  +------ ASCII A, B, C and D
 |  +--------- ASCII [
 +------------ ASCII ESC

이것이 얼마나 휴대 가능한지 잘 모르지만, 화살표 키를 잡기 위해 이와 같은 코드를 가지고 놀았습니다. q종료하려면 누르십시오 :

while read -rsn1 ui; do
    case "$ui" in
    $'\x1b')    # Handle ESC sequence.
        # Flush read. We account for sequences for Fx keys as
        # well. 6 should suffice far more then enough.
        read -rsn1 -t 0.1 tmp
        if [[ "$tmp" == "[" ]]; then
            read -rsn1 -t 0.1 tmp
            case "$tmp" in
            "A") printf "Up\n";;
            "B") printf "Down\n";;
            "C") printf "Right\n";;
            "D") printf "Left\n";;
            esac
        fi
        # Flush "stdin" with 0.1  sec timeout.
        read -rsn5 -t 0.1
        ;;
    # Other one byte (char) cases. Here only quit.
    q) break;;
    esac
done

(작은 노트로서 당신은 또한 ()에 진 (39)에 대한 테스트 예정 -. 진수 16 진수 사이의 호환 문제 같은 외모를 이스케이프 시퀀스에서 첫 번째 바이트는 ASCII 값 ESC 이며, 진수 27 진수 0x1b, 동안 진수 39 진수입니다 0x27. )