Você (provavelmente) leu primeiro de dois + bytes. $keycodeno seu script seria ESC quando a tecla seta for pressionada.
As teclas de seta podem ser:
\x1b + some value
Ele sempre é avaliado como verdadeiro devido à falta de espaços na expressão condicional.
Edit: uma atualização sobre essa declaração.
Seu ifopera no status de saída do [comando. O [comando é equivalente a test. O fato de ser um comando é um fato muito importante. Como um comando, ele requer espaços entre argumentos. O [comando é ainda mais especial, pois requer ]como último argumento.
[ EXPRESSION ]
O comando sai com o status determinado por EXPRESSION. 1 ou 0, verdadeiro ou falso .
É não uma forma exótica de escrever parêntesis. Em outras palavras, não faz parte da ifsintaxe, como por exemplo em C:
if (x == 39)
De:
if [ "$keycode"=39 ]; then
você emite:
[ "$keycode"=39 ]
que se expande para
[ \x1b=39 ]
aqui \x1b=39é lido como um argumento. Quando testou [é dado um argumento, ele sai com false apenas se EXPRESSION for nulo - o que nunca será. Mesmo se $keycodeestivesse vazio, resultaria em =39(que não é nulo / vazio).
Outra maneira de ver é que você diz:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
Leia estas perguntas e respostas para obter mais detalhes - assim como a discussão sobre [vs [[:
Nesse sentido, você também pode pesquisar os ticks anteriores `` vs $( )
Sequência de escape multibyte com teclas de seta:
Como mencionado na parte superior: Você (provavelmente) leu primeiro de dois + bytes. $keycodeno seu script seria ESC quando a tecla seta for pressionada.
As setas e outras teclas especiais resultam em sequências de escape a serem enviadas ao sistema. O byte ESC sinaliza que "aqui estão alguns bytes que devem ser interpretados de maneira diferente" . Quanto teclas de seta que seria o ASCII [seguido por ASCII A, B, Cou D.
Em outras palavras, você deve analisar três bytes ao lidar com as teclas de seta.
Você pode tentar algo na direção disso para verificar:
{ 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
Produção:
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
Não tenho certeza de como isso é portátil, mas já brincamos com códigos como este para pegar as teclas de seta. Pressione qpara sair:
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
(Como nota secundária, você também (pretende) testar contra o decimal 39 - que se parece com uma mistura entre decimal e hexadecimal. O primeiro byte de uma sequência de escape é o valor ASCII ESC , que é decimal 27 e hexadecimal 0x1b, enquanto o decimal 39 é hexadecimal 0x27. )