bashscript는 오른쪽 화살표 키를 눌렀는지 감지합니다.

bashscript는 오른쪽 화살표 키를 눌렀는지 감지합니다.

키코드가 오른쪽 화살표 키가 아닌 경우에도 항상 true를 감지하는 이유는 무엇입니까?

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

답변1

(아마도) 먼저 2바이트 이상을 읽었을 것입니다. $keycode화살표 키를 누르면 스크립트에서 ESC가 됩니다.

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

\x1b + some value

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

편집: 이 진술을 업데이트하십시오.

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

[ EXPRESSION ]

명령은 EXPRESSION에 의해 ​​결정된 상태로 종료됩니다. 1 또는 0,진짜또는잘못된.

이것은아니요괄호를 쓰는 이상한 방법. 다시 말해서아니요구문의 일부( if예: C:)

if (x == 39)

통과:

if [ "$keycode"=39 ]; then

당신은 다음을 발행합니다:

[ "$keycode"=39 ]

다음으로 확장

[ \x1b=39 ]

여기서는 다음 \x1b=39과 같이 읽습니다하나토론. 언제 test또는[ 주어졌는가하나매개변수가 false로 종료됩니다.~하지 않는 한EXPRESSION은 비어 있습니다. 이는 결코 사실이 아닙니다. $keycode비어 있어도 결과는 =39(비어 있지 않음/null)입니다.

그것을 보는 또 다른 방법은 다음과 같습니다.

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

[자세한 내용과 vs에 대한 토론을 보려면 다음 질문과 답변을 읽어보세요 [[.

이와 관련하여 백틱 대 백틱을 살펴볼 수도 있습니다.$( )


화살표 키가 포함된 멀티바이트 이스케이프 시퀀스:

상술 한 바와 같이:(아마도) 먼저 2바이트 이상을 읽었을 것입니다. $keycode화살표 키를 누르면 스크립트에서 ESC가 됩니다.

화살표 및 기타 특수 키로 인해이스케이프 시퀀스시스템으로 보냅니다. 이것ESC바이트신호"여기에는 다르게 해석되어야 하는 일부 바이트가 나타납니다.". 화살표 키는 ASCII [다음에 ASCII A또는 입니다 B.CD

즉, 화살표 키를 처리할 때 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

(작은 참고로, 십진수와 16진수가 혼합된 것처럼 보이는 십진수 39에 대해서도 테스트할 예정입니다. 이스케이프 시퀀스의 첫 번째 바이트는 다음과 같습니다.ASCII 값 ESC,지금 바로소수27 및 16진수 0x1b, 반면소수39는 16진수입니다 0x27. )

관련 정보