키 코드가 오른쪽 화살표 키가 아니더라도 왜 항상 참으로 감지합니까?
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
키 코드가 오른쪽 화살표 키가 아니더라도 왜 항상 참으로 감지합니까?
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
. )
=
는 테스트 에서 부호를 둘러싼 공백이 없기 때문에 비어 있지 않은 문자열로 구문 분석되므로 사실입니다. 화살표 키가 여러 바이트라는 사실은 별도의 문제입니다.
[
이 내장 된 명령 이라면 사람들은 왜 공간이 훨씬 더 중요한지를 파악합니다. (괄호 대신 대괄호를 사용하는 것은 bash의 이상한 방법이 아닙니다.) 이제는 부족합니다. 다시 한 번 업데이트하십시오.