Co to jest Linux równoważny pauzie DOS?

236

Mam skrypt powłoki Bash, w którym chciałbym wstrzymać wykonywanie, dopóki użytkownik nie naciśnie klawisza. W systemie DOS można to łatwo zrobić za pomocą polecenia „pauza”. Czy w skrypcie jest odpowiednik systemu Linux?

jt.
źródło

Odpowiedzi:

329

read robi to:

user@host:~$ read -n1 -r -p "Press any key to continue..." key
[...]
user@host:~$ 

W -n1precyzuje, że czeka tylko dla pojedynczego znaku. Przełącza -rgo w tryb raw, co jest konieczne, ponieważ w przeciwnym razie naciśnięcie ukośnika spowoduje, że nie zarejestruje się, dopóki nie naciśniesz następnego klawisza. W -pOkreśla polecenia, które muszą być cytowane, jeżeli zawiera spacje. keyArgument jest konieczne tylko wtedy, jeśli chcesz wiedzieć, który klucz one wciśnięty, w którym to przypadku można uzyskać do niego dostęp za pośrednictwem $key.

Jeśli używasz Bash, możesz także określić limit czasu -t, co spowoduje, że read zwróci błąd, gdy klawisz nie zostanie naciśnięty. Na przykład:

read -t5 -n1 -r -p 'Press any key in the next five seconds...' key
if [ "$?" -eq "0" ]; then
    echo 'A key was pressed.'
else
    echo 'No key was pressed.'
fi
Jim
źródło
5
Dokładnie tak byłoby "Enter any non-NUL character to continue". Niektóre klawisze nie wysłać dowolny znak (np Ctrl...), a niektóre wysłać więcej niż jedną (jak F1, Home...). bashignoruje znaki NUL.
Stephane Chazelas
2
Zwykle lepiej jest poprosić o konkretny klucz, taki jak Enter, spacja lub Y. „DOWOLNY” może być mylący dla niektórych użytkowników, istnieje klawisz TAB, więc dlaczego nie ma DOWOLNEGO klawisza, a na pewno istnieją klucze, które są potencjalnie niebezpieczne jak ESCAPE, CTRL, CMD, przycisk zasilania itp. To nie jest już tak istotne, ponieważ w dzisiejszych czasach konsola jest zwykle używana tylko przez zaawansowanych użytkowników komputerów, którzy poprawnie interpretują „DOWOLNY klucz”. Podręcznik projektowania Apple 2, choć dość stary, ma interesującą sekcję poświęconą temu tematowi ( apple2scans.net/files/1982-A2F2116-m-a2e-aiiedg.pdf ).
Gellweiler,
3
Jeśli zamiast tego użyjesz wiadomości, Press a key to continue...nawet początkujący użytkownicy będą mogli znaleźć aklucz i nacisnąć go; o)
DJDaveMark
1
Będzie to miało problemy z command | myscript.shlub myscript.sh | command. Zobacz tę odpowiedź, aby znaleźć rozwiązanie.
Tom Hale
Jeśli ktoś dostanie read: 1: read: Illegal option -npolecenie, zapakuj swoje polecenie bash -c 'command && command'itp., Ponieważ prawdopodobnie wystąpił ten błąd sh. Robię to w poleceniu otoki Lando.
Elijah Lynn,
155

Używam tych sposobów, które są bardzo krótkie i są one jak rozwiązania @theunamedguy i @Jim, ale oprócz tego mają limit czasu i tryb cichy.

Szczególnie podoba mi się ostatni przypadek i używam go w wielu skryptach, które działają w pętli, dopóki użytkownik nie naciśnie Enter.

Polecenia

  • Wprowadź rozwiązanie

    read -rsp $'Press enter to continue...\n'
  • Rozwiązanie ucieczki (z -d $ '\ e')

    read -rsp $'Press escape to continue...\n' -d $'\e'
  • Dowolne kluczowe rozwiązanie (z -n 1)

    read -rsp $'Press any key to continue...\n' -n 1 key
    # echo $key
  • Pytanie z wybranym wyborem (z -ei $ 'Y')

    read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;
    # echo $key
  • Limit czasu (z -t 5)

    read -rsp $'Press any key or wait 5 seconds to continue...\n' -n 1 -t 5;
  • Usprawniony alias

    read -rst 0.5; timeout=$?
    # echo $timeout

Wyjaśnienie

-r określa tryb raw, który nie pozwala na łączenie znaków takich jak „\” lub „^”.

-s określa tryb cichy, a ponieważ nie potrzebujemy danych wyjściowych z klawiatury.

-p $ „ podpowiedź określa podpowiedź, która musi znajdować się między $ a „, aby pozwolić na spacje i znaki ucieczki. Uważaj, musisz umieścić między pojedynczymi cudzysłowami symbol dolara, aby skorzystać ze znaków, które nie mają znaczenia, w przeciwnym razie możesz użyć prostych cudzysłowów.

-d $ ' \ e ' określa znak ucieczki jako znak separatora, więc jako znak końcowy dla bieżącego wpisu można wstawić dowolny znak, ale należy zachować ostrożność, aby wstawić znak, który użytkownik może wpisać.

-n 1 określa, że ​​potrzebuje tylko jednego znaku.

-e określa tryb readline.

-i $ ' Y ' określa Y jako tekst początkowy w trybie readline.

-t 5 określa limit 5 sekund

klawisz służy na wypadek, gdybyś musiał znać wejście, w przypadku -n1, klawisz, który został naciśnięty.

$? służą do poznania kodu wyjścia ostatniego programu, do odczytu, 142 w przypadku przekroczenia limitu czasu, 0 prawidłowe wprowadzanie. Włożyć $? w zmiennej tak szybko, jak to możliwe, jeśli trzeba ją przetestować po niektórych komendach, ponieważ wszystkie komendy przepisałyby $?

y.petremann
źródło
1
+1 za wyjaśnienie -s; man readi read --helppomoc nie pomogła w Ubuntu 10.04.1 LTS. Edycja: help readzrobiono; czy reszta jest przestarzała?
Cees Timmerman
1
1+ za świetne wyjaśnienie: ale dostałem read: -i: invalid optionza ex. read -rp $'Are you sure (Y/n) : ' -ei $'Y' key;na #osx read -rp $'kill-server: Are you sure (Y/n) : ' -d $'Y' key;zamiast tego działa dla mnie. `
Tino Rüb
Nie wiem, jak to działa na OSX, ale zrobiłem test i -idziała doskonale na Ubuntu, również nie wiem, czy -ddziała tak samo na OSX.
y.petremann
można szybko i przyjemnie obejść monit za pomocą echa przed odczytem, ​​ostatecznie echo -n
THESorcerer 13.03.19
15

readbez żadnych parametrów będzie kontynuowane tylko po naciśnięciu Enter. Polecenie DOS pausebędzie kontynuowane po naciśnięciu dowolnego klawisza. Użyj, read –n1jeśli chcesz tego zachowania.

xsl
źródło
15

To działało dla mnie w wielu odmianach Linuksa, gdzie niektóre z tych innych rozwiązań nie (w tym najpopularniejsze tutaj). Myślę, że to też jest bardziej czytelne ...

echo Press enter to continue; read dummy;

Zauważ, że zmienną należy podać jako argument dla read.

BuvinJ
źródło
ta odpowiedź rozwiązuje mój problem, jeśli skopiuję i wkleję ten wiersz i z jakiegoś powodu dodam więcej wierszy, dołączone wiersze nie zostaną wykonane, tak jak w przypadku pauzy DOS
Sérgio
10

read -n1nie jest przenośny. Przenośnym sposobem na zrobienie tego samego może być:

(   trap "stty $(stty -g;stty -icanon)" EXIT
    LC_ALL=C dd bs=1 count=1 >/dev/null 2>&1
)   </dev/tty

Oprócz użycia read, po prostu naciśnij, ENTERaby kontynuować monit, możesz:

sed -n q </dev/tty
mikeserv
źródło
2
status=noneteż nie jest przenośny. Zamiast tego przekieruj stdout i stderr do / dev / null. read -r line < /dev/ttybyłoby wystarczających dla prasy ENTER ... .
Stephane Chazelas
@StephaneChezales dzięki - nie wiedziałem o tym. źle to teraz naprawię. Jeszcze raz dziękuję - naprawione. Nawiasem mówiąc, jesteś bezdenną studnią wartościowych informacji.
mikeserv
1
Zwróć także uwagę na to, settings=$(stty -g); stty raw; dd ...; stty "$settings"aby zapisać i przywrócić ustawienia tty.
Stephane Chazelas
@StephaneChezales - nie jestem przy komputerze - czy uważasz, że tredytowanie też mogłoby działać?
mikeserv
1
Nie, ponieważ trbuforowałby dane wyjściowe jako potok, a klawiatury spoza USA mają klucze wysyłające znaki spoza \1-\177zakresu. ddjest tutaj idiomatyczny sposób.
Stephane Chazelas
2

Jeśli po prostu chcesz zatrzymać pętlę lub skrypt i z przyjemnością naciśniesz Enter zamiast dowolnego klawisza, wtedy readsam to zrobi.

do_stuff
read
do_more_stuff

Nie jest przyjazny dla użytkownika końcowego, ale może wystarczyć w przypadkach, gdy piszesz szybki skrypt dla siebie i musisz go zatrzymać, aby zrobić coś ręcznie w tle.

mwfearnley
źródło
To prawda, ale w przypadku bazy danych najbardziej pomocny jest przykład.
SDsolar
Dzięki, wziąłem twoją radę na pokład. Po prostu napisanie nazwy polecenia nie jest bardzo jasne z perspektywy czasu.
mwfearnley
1

Spróbuj tego:

function pause(){
   read -p "$*"
}
Alex Fort
źródło
1
Czy ktoś może wyjaśnić, dlaczego jest to odrzucone? Czy to z powodu braku treści, czy jest to złe rozwiązanie?
3ocen
4
@ 3ocene Nie pokazuje użycia utworzonej funkcji; plus brak jakiegokolwiek wyjaśnienia.
parvus
Zgoda. Czy możesz podać przykład wywoływania tej funkcji?
SDsolar
1

Ta funkcja działa zarówno w trybie, jak bashi zshzapewnia we / wy 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

Włóż to .{ba,z}shrcdo Wielkiej Sprawiedliwości!

Tom Hale
źródło
0

Tak, aby użyć read- i jest kilka poprawek, które sprawiają, że jest najbardziej przydatny zarówno cronw terminalu, jak i w nim.

Przykład:

time rsync (options)
read -n 120 -p "Press 'Enter' to continue..." ; echo " "

-N 120 powoduje przekroczenie limitu czasu odczytu instrukcji po 2 minutach, więc się nie blokuje cron.

W terminalu daje 2 minuty, aby zobaczyć, jak długo rsynctrwało wykonanie polecenia.

Potem echojest następna, więc kolejny wiersz bash pojawi się w następnym wierszu.

W przeciwnym razie pojawi się w tej samej linii bezpośrednio po „kontynuuj ...” po Enternaciśnięciu w terminalu.

SDsolar
źródło