naciśnij spację aby kontynuować

73

Jak zatrzymać skrypt bash, dopóki użytkownik nie naciśnie Space?

Chciałbym mieć pytanie w swoim skrypcie

Naciśnij spację, aby kontynuować lub CTRL+, Caby wyjść

a następnie skrypt powinien się zatrzymać i poczekać, aż zostanie naciśnięty klawisz Space.

rubo77
źródło
Wszystko to i więcej zostało omówione w tym SO Q&A BTW: Jaki jest linux równoważny pauzie DOS?
slm
powiązane: unix.stackexchange.com/questions/293940/…
Trevor Boyd Smith

Odpowiedzi:

58

Możesz użyć read:

read -n1 -r -p "Press space to continue..." 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
Aleksander Ksenia
źródło
12
Powinieneś dodać -s, aby nie drukować wciśniętego znaku na terminalu. I dodaj podział linii na końcu, w przeciwnym razie dane wyjściowe będą 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'
rubo77
1
Ten skrypt nie działa. Właśnie przetestowałem go na linuksie Red Hata ... elseBlok zawsze działa, nawet po naciśnięciu spacji.
Robert
3
@robert To dlatego, że nie używasz bash. Działa, jeśli używasz read _zamiast tego, jeśli masz inną powłokę niż bash.
Niklas Rosencrantz
Czy w ''środku powinna znajdować się spacja?
Jose Antonio Dura Olmos
To jest ''na pusty ciąg. Brak miejsca w środku. Sądzę, że pasuje również, jeśli wpiszesz ENTER lub TAB
rubo77
44

Metoda omówiona w tym SO Q&A jest prawdopodobnie najlepszym kandydatem na alternatywę dla pausezachowania, do którego przyzwyczajasz się w systemie Windows podczas wykonywania plików BAT.

$ read -rsp $'Press any key to continue...\n' -n1 key

Przykład

Tutaj uruchamiam powyższe, a następnie po prostu naciskam dowolny klawisz, w tym przypadku Dklawisz.

$ read -rsp $'Press any key to continue...\n' -n1 key
Press any key to continue...
$ 

Bibliografia

slm
źródło
Mam na myśli dlaczego $przed ciąg tutaj tutaj -rsp $'Press:?
rubo77
2
@ rubo77 - ah. W ten sposób możesz napisać dosłownie ciąg znaków specjalnych. Ma postać: $ '...'
slm
1
@ rubo77 - to jest inne. To znak dolara z podwójnymi cudzysłowami, użyłem dolara z pojedynczymi cudzysłowami. Usuń ten komentarz, jest nieprawidłowy.
slm
1
Oh rozumiem. Jeśli wstawisz sekwencje specjalne w ciągu zachęty. patrz wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77
@ rubo77 - tak, że notacja pozwala na dołączenie sekwencji specjalnych bez dodatkowych echo -e "..."linii. W takich sytuacjach jest znacznie bardziej kompaktowy.
slm
6
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 drukuje wiersz bez spływu nowej linii, uchwyty CTRL+Cniezawodnie wywołuje sttytylko tak często, jak to konieczne, i przywraca tty kontrolnego dokładnie do stanu, w którym sttyznalazł. Poszukaj man sttyinformacji o tym, jak jawnie kontrolować echa, kontrolować znaki i wszystko.

Możesz także to zrobić:

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żesz to zrobić ENTERbez [testów ]i bez stty:

sed -n q </dev/tty
mikeserv
źródło
5

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 skrypcie:

pause
rubo77
źródło
jeśli dopiero zaczynasz korzystać ze skryptów powłoki - przed użyciem musisz umieścić tę funkcję u góry skryptu
Richard
3

leniwy jeden wkładka:

echo "Press any key to continue or Ctrl+C to cancel"
read && do_something.sh

wadą jest utrata kontroli, gdy użytkownik naciśnie ctrl + c. W takim przypadku skrypt zawsze kończy działanie z kodem 130.

gcb
źródło
2

Ustawienia IFSpustego ciągu pomijają domyślne zachowanie przycinania białych znaków podczas odczytu.

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

AKTUALIZACJA 23.05.2018: Możemy to uprościć, używając zmiennej REPLY, która nie podlega podziałowi słów:

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
Robin A. Meade
źródło
1

Oto sposób, który działa w obie bashi zshoraz zapewnia I / O 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

Włóż to do swojej .{ba,z}shrcWielkiej Sprawiedliwości!

Tom Hale
źródło