bashscript para detectar la tecla de flecha derecha presionada

9

¿Por qué esto siempre se detecta como verdadero, incluso si el código clave no es la tecla de flecha derecha?

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
Confundido
fuente
stackoverflow
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Respuestas:

16

Usted (probablemente) lea primero de dos + bytes. $keycodeen 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 ifopera 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 ifsintaxis 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=39se lee como un argumento. Cuando testo [se le da un argumento, sale con falso solo si EXPRESSION es nulo, lo cual nunca será. Incluso si $keycodeestuviera 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. $keycodeen 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, Co 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 qpara 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. )

usuario367890
fuente
2
El primer problema en la pregunta es que no hay espacios alrededor del =signo en la prueba, por lo que se analiza simplemente como una cadena no vacía y, por lo tanto, es cierto. El hecho de que las teclas de flecha sean de varios bytes es un problema separado.
wurtel
2
Hmm, esa oración no tiene mucho contexto como está, lo leí porque pensé que era parte de la explicación de secuencias de varios bytes que ya conocía.
wurtel
2
@wurtel: Sí Vago, supongo. Encuentre que una vez que una explicación [es un comando incorporado, la gente comprende por qué los espacios son importantes mucho más rápidamente. (No es simplemente una forma extraña de golpear con corchetes en lugar de paréntesis). Hay que salir corriendo ahora. Actualizar una vez de vuelta.
user367890