Wie stoppt man ein Bash-Skript mit der Leertaste?

Wie stoppt man ein Bash-Skript mit der Leertaste?

Ich arbeite an einer in Bash geschriebenen Stoppuhr in Form eines Zauberwürfels und möchte diese durch Drücken der Leertaste stoppen, da Ctrl+ Cnicht möglich ist, wenn man sie so schnell wie möglich beenden muss.

Gibt es eine Möglichkeit, das Programm nur mit der Leertaste zu stoppen?

Ich habe den Befehl nachgeschlagen, killkonnte ihn aber nicht herausfinden.

Der Stoppuhrteil des Codes ist unten:

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf "\r$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

Antwort1

Es ist Ihr Terminal, das SIGINT an die Vordergrundprozessgruppe sendet, wenn Sie Ctrl+ drücken c. Sie können es so konfigurieren, dass dies bei jedem Zeichen geschieht, aber Sie möchten die alten Einstellungen wiederherstellen, wenn das Skript beendet wird.

#!/bin/bash

settings="$(stty -g)"
trap 'stty "$settings"' EXIT
stty intr ' '

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

settings="$(stty -g)"speichert die alten Einstellungen; stty intr ' 'lässt das Terminal auf Spacestatt auf Ctrl+ reagieren c; trap 'stty "$settings"' EXITist für die Wiederherstellung der alten Einstellungen beim Beenden des Skripts verantwortlich.

Anmerkungen:

  • Im Code der Falle stty $settingsist besser als stty "$settings". Es ist eine Ausnahme von der "immer zitieren"-Regel. Anführungszeichen verhindern die Worttrennung und die Generierung von Dateinamen (Globbing), aber einige Implementierungen von sttyerfordern möglicherweise die Worttrennung, für diese darf die Variable nicht in Anführungszeichen gesetzt werden. Um schädliche Nebeneffekte der Generierung von Dateinamen zu vermeiden,Spezifikationerfordert stty -gdie Generierung einer Zeichenfolge, die diese Funktion nicht auslöst.

    Bearbeiten:das war ein Defekt in der POSIX-Spezifikation. Der obige Code wurde behoben.

  • Falls etwas schief geht und Sie sich in einer interaktiven Shell befinden, die Spaceimmer noch SIGINT generiert, müssen Sie es manuell aufrufen . Der Befehl enthält Leerzeichen, aber denken Sie daran, dass Sie durch Drücken von + stty intr ^Cimmer noch ein Leerzeichen eingeben können .Ctrlv Space

  • Ich habe es verwendet printf '\r%s' …, weil ich denke, dass ein statisches Format und dynamische Daten besser zur „Philosophie“ passen printfals das von Ihnen verwendete dynamische Format.

" Spacestatt Ctrl+ c" bedeutet, wenn Spaceetwas Besonderes wird, hört Ctrl+ cauf, etwas Besonderes zu sein. Man kann es einen Fehler nennen, weilBenutzer erwarten, dass Ctrl+ cetwas Besonderes bleibt. Beides gleichzeitig speziell zu machen ist allerdings nicht trivial, ich glaube nicht, dass dies durch die Konfiguration des Terminals möglich ist.

Diese alternative Version stoppt bei fast jeder Taste, während Ctrl+ cwie gewohnt funktioniert:

#!/bin/bash

while read -r -t 0.001; do :; done    # dump the buffer
TMP0=$(date +%s%N)
until read -r -n 1 -t 0.001; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
echo

Damit es reagiert, Spacemüssen Sie nur überprüfen, was gelesen wurde:


until read -r -n 1 -t 0.001 && [ "$REPLY" = ' ' ]; do

Beachten Sie, dass der Mechanismus zum SpaceStoppen des Skripts jetzt ganz anders ist als die Funktionsweise von Ctrl+ c.

Antwort2

Wenn du die Stoppuhr nicht benötigst, sondern am Ende sowieso nur die benötigte Zeit wissen willst, dann kannst du Folgendes verwenden:

time read -r -n 1

Sie erhalten eine Ausgabe wie:

time read -r -n 1

real    1m30.909s
user    0m0.000s
sys     0m0.000s

und stoppt bei praktisch jedem Tastendruck (ähnlich wie Kamil verwendet read)

oder wenn Sie nur den Zeitteil möchten:

{ time read -r -n 1; } 2>&1 | grep real | awk '{ print $2 }'

mit freundlicher Genehmigung vonrici

verwandte Informationen