Нажмите пробел, чтобы продолжить

74

Как остановить скрипт bash, пока пользователь не нажал Space?

Я хотел бы иметь вопрос в моем сценарии

Нажмите пробел, чтобы продолжить, или CTRL+, Cчтобы выйти

и затем скрипт должен остановиться и ждать, пока не будет нажата клавиша пробела.

rubo77
источник
Все это и многое другое рассмотрено в этом SO Q & A Кстати: что такое linux эквивалентно паузе DOS?
slm
связанные: unix.stackexchange.com/questions/293940/…
Тревор Бойд Смит

Ответы:

58

Вы можете использовать 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
AleksanderKseniya
источник
12
Вы должны добавить -s, чтобы не печатать нажатый символ на терминале. И добавьте разрыв строки в конце, иначе вывод будет продолжен в той же строке, что и вопрос. Лучше всего будет:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77
1
Этот скрипт не работает. Только что проверил на Red Hat Linux ... elseБлок всегда работает, даже когда нажата пробел.
Роберт
3
@robert Это потому что ты не используешь bash. Это работает, если вы используете read _вместо этого, если у вас есть другая оболочка, чем bash.
Никлас Розенкранц
Должен ли ''содержать пробел внутри?
Хосе Антонио Дура Олмос
Это ''для пустой строки. Нет места внутри. Я думаю, это также подходит, если вы введете ENTER или TAB
rubo77
45

Метод, обсуждаемый в этом SO Q & A, вероятно, является лучшим кандидатом на альтернативу pauseповедению, которое вы привыкли в Windows при работе с файлами BAT.

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

пример

Здесь я запускаю вышеизложенное, а затем просто нажимаю любую клавишу, в данном случае Dклавишу.

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

Рекомендации

SLM
источник
Я имею в виду, почему $перед строкой здесь -rsp $'Press:?
rubo77
2
@ rubo77 - ах. Вот как вы можете сделать буквальную строку со специальными символами. Он имеет вид: $ '...'
slm
1
@ rubo77 - это другое. Это знак доллара с двойными кавычками, я использовал доллар с одинарными кавычками. Пожалуйста, удалите этот комментарий, это неправильно.
SLM
1
Я понимаю. В случае, если вы поместили экранированные последовательности в строку подсказки. см. wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77
@ rubo77 - да, это обозначение позволяет включать escape-последовательности без каких-либо дополнительных echo -e "..."строк. В таких ситуациях он намного компактнее.
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"

Теперь он печатает подсказку без завершающего символа новой строки, CTRL+Cнадежно обрабатывает , вызывает sttyтолько столько раз, сколько необходимо, и восстанавливает контрольный tty до того состояния, в котором sttyон находился . Посмотрите на man sttyинформацию о том, как явно контролировать эхо, символы управления и все.

Вы также можете сделать это:

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

Вы могли бы сделать это ENTERбез [тестов ]и ничего sttyподобного:

sed -n q </dev/tty
mikeserv
источник
5

Вы можете создать для него функцию:

pause(){
 read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
}

Тогда вы можете использовать это везде в вашем скрипте:

pause
rubo77
источник
если вы новичок в написании сценариев оболочки - вам нужно поместить функцию в верхнюю часть вашего сценария, прежде чем ее использовать
Ричард
3

ленивый лайнер:

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

недостаток в том, что вы теряете контроль, когда пользователь нажимает Ctrl + C. В этом случае скрипт всегда завершается с кодом 130.

GCB
источник
2

Настройки IFSдля пустой строки подавляют поведение чтения по умолчанию обрезки пробела.

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

ОБНОВЛЕНИЕ 2018-05-23: мы можем упростить это, используя переменную REPLY, которая не разделяется на слова:

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
Робин А. Мид
источник
1

Вот способ, который работает как bashи zsh, и обеспечивает ввод / вывод в терминал:

# 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

Поместите это .{ba,z}shrcдля Великой Справедливости!

Том Хейл
источник