Bashscript, um zu erkennen, dass die rechte Pfeiltaste gedrückt wird

9

Warum wird dies immer als wahr erkannt, auch wenn der Schlüsselcode nicht die rechte Pfeiltaste ist?

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
ConfusedStack
quelle
verwandte stackoverflow.com/questions/22842896/…
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功

Antworten:

16

Sie lesen (wahrscheinlich) zuerst aus zwei + Bytes. $keycodeIn Ihrem Skript wäre ESC, wenn die Pfeiltaste gedrückt wird.

Pfeiltasten können sein:

\x1b + some value

Es wird immer als wahr ausgewertet, da Leerzeichen im bedingten Ausdruck fehlen.

Bearbeiten: eine Aktualisierung dieser Anweisung.

Sie ifbearbeiten den Exit-Status des [Befehls. Der [Befehl entspricht test. Die Tatsache, dass es sich um einen Befehl handelt, ist eine sehr wichtige Tatsache. Als Befehl sind Leerzeichen zwischen Argumenten erforderlich. Der [Befehl ist insofern etwas Besonderes, als er ]als letztes Argument benötigt wird.

[ EXPRESSION ]

Der Befehl wird mit dem durch EXPRESSION festgelegten Status beendet. 1 oder 0, wahr oder falsch .

Es ist keine exotische Art, Klammern zu schreiben. Mit anderen Worten, es ist nicht Teil der ifSyntax wie zum Beispiel in C:

if (x == 39)

Durch:

if [ "$keycode"=39 ]; then

Sie geben aus:

[ "$keycode"=39 ]

das erweitert sich zu

[ \x1b=39 ]

Hier \x1b=39wird als ein Argument gelesen . Wenn testoder [wenn ein Argument angegeben wird, wird es nur dann mit false beendet , wenn EXPRESSION null ist - was niemals der Fall sein wird. Selbst wenn $keycodees leer wäre, würde es dazu führen =39(was nicht null / leer ist).

Eine andere Sichtweise ist, dass Sie sagen:

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

Lesen Sie diese Fragen und Antworten für weitere Details - sowie eine Diskussion über [vs [[:

In dieser Hinsicht könnten Sie auch Zecken `` vs. $( )


Multibyte-Escape-Sequenz mit Pfeiltasten:

Wie oben erwähnt: Sie lesen (wahrscheinlich) zuerst aus zwei + Bytes. $keycodeIn Ihrem Skript wäre ESC, wenn die Pfeiltaste gedrückt wird.

Pfeil und andere Sonderschlüssel führen dazu, dass Escape-Sequenzen an das System gesendet werden. Das ESC- Byte signalisiert, dass "hier einige Bytes kommen, die anders interpretiert werden sollten" . Wie für den Pfeiltasten , die die ASCII sein würde , [gefolgt von ASCII A, B, Coder D.

Mit anderen Worten, Sie müssen drei Bytes analysieren, wenn Sie mit Pfeiltasten arbeiten.

Sie könnten etwas in diese Richtung versuchen, um zu überprüfen:

{   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

Ausbeute:

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

Ich bin mir nicht sicher, wie portabel dies ist, habe aber früher mit Code wie diesem herumgespielt, um Pfeiltasten zu fangen. Drücken Sie qzum Beenden:

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

(Als kleine Anmerkung (beabsichtigen Sie auch), gegen Dezimal 39 zu testen - was wie eine Verwechslung zwischen Dezimal und Hexadezimal aussieht. Das erste Byte in einer Escape-Sequenz ist der ASCII-Wert ESC , der Dezimal 27 und Hexadezimal ist 0x1b, während Dezimal 39 Hexadezimal ist 0x27. )

user367890
quelle
2
Das erste Problem bei der Frage ist, dass das =Zeichen im Test nicht durch Leerzeichen umgeben ist. Daher wird es einfach als nicht leere Zeichenfolge analysiert und ist daher wahr. Die Tatsache, dass Pfeiltasten mehrere Bytes sind, ist ein separates Problem.
Wurtel
2
Hmm, dieser Satz hat nicht viel Kontext wie er ist, ich habe darüber gelesen, da ich dachte, dass dies Teil der Erklärung von Mehrbyte-Sequenzen ist, die ich bereits kannte.
Wurtel
2
@wurtel: Ja. Zu vage, denke ich. Finden Sie heraus, dass Menschen , sobald eine Erklärung [ein eingebauter Befehl ist, schneller verstehen , warum Räume wichtig sind. (Es ist nicht einfach eine seltsame Art, Klammern anstelle von Klammern zu verwenden.) Sie müssen jetzt ausgehen. Einmal zurück aktualisieren.
user367890