Натисніть пробіл, щоб продовжити


73

Як зупинити bash-скрипт, поки користувач не натисне Space?

Я хотів би, щоб це питання було в моєму сценарії

Натисніть пробіл, щоб продовжити, або CTRL+, Cщоб вийти

а потім сценарій повинен зупинитися і чекати, поки натисне пробіл.


Все це та інше розглянуто в цьому запитанні та запитаннях BTW: Що таке еквівалент Linux для паузи DOS?
slm


Відповіді:


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

12
Ви повинні додати –s, щоб не друкувати натиснутий символ на терміналі. І додайте рядок рядка в кінці, інакше результат буде продовжуватися безпосередньо в тому ж рядку, що і питання. Кращим було б:read -n1 -rsp $'Press any key to continue or Ctrl+C to exit...\n'
rubo77

1
Цей сценарій не працює. Тільки тестував його на Linux Hat Red Hat ... elseБлок завжди працює, навіть коли натискається пробіл.
Роберт

3
@robert Це тому, що ти не використовуєш bash. Він працює, якщо ви використовуєте read _натомість, якщо у вас є інша оболонка, ніж bash.
Ніклас Розенкранц

Чи повинен ''містити простір всередині?
Жозе Антоніо Дура Олмос

Це ''для порожнього рядка. Всередині немає місця. Гадаю, це також підходить, якщо ви введете ENTER або TAB
rubo77

44

Метод, обговорюваний у цій 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...
$ 

Список літератури


Я маю на увазі, чому тут $перед рядком -rsp $'Press:?
rubo77

2
@ rubo77 - ах. Ось так ви можете зробити буквальний рядок зі спеціальними символами. Він має форму: $ '...'
slm

1
@ rubo77 - це інакше. Це знак долара з подвійними котируваннями, я використав котирування долара з одиничними. Видаліть цей коментар, це неправильно.
slm

1
Ах, я розумію. У випадку, якщо ви помістите втікаючі послідовності всередині рядка-підказок. дивіться wiki.bash-hackers.org/syntax/quoting#ansi_c_like_strings
rubo77

@ rubo77 - так, позначення дозволяє включати послідовності втечі без будь-яких зайвих 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

5

Ви можете створити для нього функцію:

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

Тоді ви можете використовувати це скрізь у своєму сценарії:

pause

якщо ви новачок в сценарії оболонок - вам потрібно поставити цю функцію у верхній частині сценарію, перш ніж її використовувати
Річард

3

ледачий один лайнер:

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

недоліком є ​​те, що ви втрачаєте контроль, коли користувач натискає ctrl + c. У цьому випадку сценарій завжди буде виходити з кодом 130.


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велику справедливість!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.