Usted (probablemente) lea primero de dos + bytes. $keycode
en su script sería ESC cuando se presiona la tecla de flecha.
Las teclas de flecha pueden ser:
\x1b + some value
Siempre se evalúa como verdadero debido a la falta de espacios en la expresión condicional.
Editar: una actualización de esa declaración.
Su if
opera en el estado de salida del [
comando. El [
comando es equivalente a test
. El hecho de que sea un comando es un hecho muy importante. Como comando requiere espacios entre argumentos. El [
comando es más especial porque requiere ]
como último argumento.
[ EXPRESSION ]
El comando sale con el estado determinado por EXPRESSION. 1 o 0, verdadero o falso .
Es no una manera exótica de paréntesis escritura. En otras palabras, es no parte de la if
sintaxis como por ejemplo en C:
if (x == 39)
Por:
if [ "$keycode"=39 ]; then
usted emite:
[ "$keycode"=39 ]
que se expande a
[ \x1b=39 ]
Aquí \x1b=39
se lee como un argumento. Cuando test
o [
se le da un argumento, sale con falso solo si EXPRESSION es nulo, lo cual nunca será. Incluso si $keycode
estuviera vacío, resultaría en =39
(que no es nulo / vacío).
Otra forma de verlo es que dices:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
Lea estas preguntas y respuestas para obtener más detalles, así como una discusión sobre [
vs [[
:
En ese sentido, también podría investigar las garrapatas `` vs $( )
Secuencia de escape multibyte con teclas de flecha:
Como se mencionó en la parte superior: (probablemente) lea primero de dos + bytes. $keycode
en su script sería ESC cuando se presiona la tecla de flecha.
Las flechas y otras teclas especiales dan como resultado que se envíen secuencias de escape al sistema. El byte ESC indica que "aquí vienen algunos bytes que deberían interpretarse de manera diferente" . En cuanto a las flechas que sería el ASCII [
seguido de ASCII A
, B
, C
o D
.
En otras palabras, debe analizar tres bytes cuando se trata de teclas de flecha.
Puede probar algo en la dirección de esto 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
Rendimiento:
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
No estoy seguro de qué tan portátil es esto, pero anteriormente he jugado con un código como este para atrapar las teclas de flecha. Presione q
para salir:
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 menor, también (tiene la intención de) probar contra el decimal 39, que parece una mezcla entre decimal y hexadecimal. El primer byte en una secuencia de escape es el valor ASCII ESC , que es decimal 27 y hexadecimal 0x1b
, mientras que el decimal 39 es hexadecimal 0x27
. )