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


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.