Jak zatrzymać skrypt bash, dopóki użytkownik nie naciśnie spacji ?
Chciałbym mieć pytanie w moim skrypcie
Naciśnij spację, aby kontynuować lub CTRL + C aby wyjść
, a następnie skrypt powinien zatrzymać się i poczekać na naciśnięcie spacji.
Komentarze
- Wszystko to i nie tylko jest omówione w tym SO Q & Przy okazji: Jaki jest odpowiednik Linuksa pauzować DOS?
- Zobacz też: Wstrzymaj skrypt powłoki do naciśnięcia klawisza Enter w pętli while
- related: unix.stackexchange.com/questions/293940/…
Odpowiedź
Możesz użyć read
:
read -n1 -s -r -p $"Press space to continue...\n" key if [ "$key" = " " ]; then # Space pressed, do something # echo [$key] is empty when SPACE is pressed # uncomment to trace else # Anything else pressed, do whatever else. # echo [$key] not empty fi
Zamień " "
zamiast spacji powyżej na ""
dla klawisza Enter, $"\t"
dla klawisza Tab.
Komentarze
- Powinieneś dodać -s, aby nie drukować wciśniętego znaku na terminalu. I dodaj podział wiersza na końcu lub wyjście będzie kontynuowane bezpośrednio w tym samym wierszu, co pytanie. Najlepiej byłoby:
read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
- Ten skrypt ' nie działa. Właśnie przetestowałem to w systemie Red Hat Linux … Blok
else
działa zawsze, nawet po naciśnięciu spacji. - @robert It ', ponieważ nie ' nie używasz
bash
. Działa, jeśli zamiast tego użyjeszread _
, jeśli masz inną powłokę niżbash
. - Czy
''
zawiera spację w środku? - To czyta z STDIN, co spowoduje problemy podane
pipeline | script.sh
Patrz tę odpowiedź , aby znaleźć rozwiązanie.
Odpowiedź
Metoda omówione w tym SO Q & A jest prawdopodobnie najlepszym kandydatem na alternatywę dla zachowania pause
, do którego „przyzwyczajasz się w systemie Windows, gdy robienie plików BAT.
$ read -rsp $"Press any key to continue...\n" -n1 key
Przykład
Tutaj uruchamiam powyższe, a następnie po prostu wciskam dowolny klawisz, w tym przypadku D .
$ read -rsp $"Press any key to continue...\n" -n1 key Press any key to continue... $
Referencje
Komentarze
- Mam na myśli, dlaczego
$
befo czy tutaj jest ciąg:-rsp $'Press
? - @ rubo77 – ah. Oto ' sposób, w jaki można utworzyć dosłowny ciąg znaków ze znakami specjalnymi. Ma ' postać: $ ' … '
- @ rubo77 – że ' jest inny. Że ' to znak dolara z podwójnymi cudzysłowami, użyłem dolara z pojedynczymi cudzysłowami. Usuń ten komentarz, ' jest zły.
- Ach, rozumiem. Na wypadek, gdybyś umieścił sekwencje ze znakami ucieczki wewnątrz łańcucha zachęty. patrz wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
- @ rubo77 – tak, że notacja pozwala na włączenie sekwencji ucieczki bez żadnych dodatkowych
echo -e "..."
linii. W takich sytuacjach ' jest znacznie bardziej zwarty.
Odpowiedź
Możesz stworzyć dla niego funkcję:
pause(){ read -n1 -rsp $"Press any key to continue or Ctrl+C to exit...\n" }
Następnie możesz użyć tego wszędzie w swoim skrypcie:
pause
Komentarze
- Jeśli nie masz doświadczenia ze skryptami powłoki – przed użyciem tej funkcji musisz umieścić tę funkcję na górze skryptu
Odpowiedź
hold=" " printf "Press "SPACE" to continue or "CTRL+C" to exit : " tty_state=$(stty -g) stty -icanon until [ -z "${hold#$in}" ] ; do in=$(dd bs=1 count=1 </dev/tty 2>/dev/null) done stty "$tty_state"
To teraz wyświetla podpowiedź bez końcowego znaku nowej linii, obsługuje CTRL+C
niezawodnie, wywołuje stty
tylko tak często, jak jest to konieczne, i przywraca kontrolujące tty dokładnie do stanu, w którym stty
znalazłem to. Zajrzyj do man stty
, aby uzyskać informacje o tym, jak jawnie kontrolować echa, znaki sterujące i wszystko inne.
Możesz także zrobić to:
printf "Press any key to continue or "CTRL+C" to exit : " (tty_state=$(stty -g) stty -icanon LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1 stty "$tty_state" ) </dev/tty
Można to zrobić za pomocą ENTER
, żadnych [
testów ]
i żadnych stty
takich jak:
sed -n q </dev/tty
Komentarze
- Twoje dwa ostatnie rozwiązania wydają się działać dobrze również z
/bin/sh
(np. we FreeBSD), nie tylko z bash. - to Twoja odpowiedź na SO odpowiednik, czy nawet lepszy?
Odpowiedź
Oto sposób, który działa zarówno w bash
i zsh
i zapewnia I / O do terminala:
# Prompt for a keypress to continue. Customise prompt with $* function pause { >/dev/tty printf "%s" "${*:-Press any key to continue... }" [[ $ZSH_VERSION ]] && read -krs # Use -u0 to read from STDIN [[ $BASH_VERSION ]] && </dev/tty read -rsn1 printf "\n" } export_function pause
Umieść to w swoim .{ba,z}shrc
dla Wielkiej Sprawiedliwości!
Odpowiedź
lazy one liner:
echo "Press any key to continue or Ctrl+C to cancel" read && do_something.sh
Wadą jest to, że tracisz kontrolę, gdy użytkownik naciśnie ctrl + c. W takim przypadku skrypt zawsze kończy pracę z kodem 130.
Odpowiedz
Ustawienia IFS
na pusty ciąg blokują domyślne zachowanie odczytu polegające na przycinaniu białych znaków.
try_this() { echo -n "Press SPACE to continue or Ctrl+C to exit ... " while true; do # Set IFS to empty string so that read doesn"t trim # See http://mywiki.wooledge.org/BashFAQ/001#Trimming IFS= read -n1 -r key [[ $key == " " ]] && break done echo echo "Continuing ..." } try_this
UPDATE 2018-05-23: Możemy to uprościć, używając zmiennej REPLY, która nie podlega podziałowi na słowa:
try_this() { echo -n "Press SPACE to continue or Ctrl+C to exit ... " while true; do read -n1 -r [[ $REPLY == " " ]] && break done echo echo "Continuing ..." } try_this
Odpowiedź
Oto proste rozwiązanie z Naciśnij SPACJĘ, aby kontynuować (nie ENTER)
read -s -d " "
Poczekaj, aż naciśniesz spację. Tak, tylko spacja, nie pęknie, jeśli naciśniesz Enter.