Как мне запросить Да / Нет / Отменить ввод в сценарии оболочки Linux? - PullRequest
1267 голосов
/ 22 октября 2008

Я хочу приостановить ввод в сценарии оболочки и предложить пользователю выбор. Стандартный вопрос типа «Да, Нет или Отмена». Как мне сделать это в типичной командной строке?

Ответы [ 28 ]

17 голосов
/ 15 ноября 2013

Это решение читает один символ и вызывает функцию с ответом "да".

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi
17 голосов
/ 09 мая 2012

Используйте команду read:

echo Would you like to install? "(Y or N)"

read x

# now check if $x is "y"
if [ "$x" = "y" ]; then
    # do something here!
fi

а затем все остальные вещи, которые вам нужны

12 голосов
/ 19 апреля 2015
read -e -p "Enter your choice: " choice

Опция -e позволяет пользователю редактировать ввод с помощью клавиш со стрелками.

Если вы хотите использовать предложение в качестве ввода:

read -e -i "yes" -p "Enter your choice: " choice
Опция

-i выводит подсказки.

10 голосов
/ 21 мая 2014

Извините за публикацию на такой старый пост. Несколько недель назад я столкнулся с подобной проблемой, в моем случае мне нужно было решение, которое также работало в онлайн-установочном скрипте, например: curl -Ss https://raw.github.com/_____/installer.sh | bash

Использование read yesno < /dev/tty прекрасно работает для меня:

echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty

if [ "x$yesno" = "xy" ];then

   # Yes
else

   # No
fi

Надеюсь, это кому-нибудь поможет.

8 голосов
/ 06 апреля 2014

Чтобы получить красивое поле ввода, похожее на ncurses, используйте команду dialog вот так:

#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then 
    echo "Let's do something risky"
    # do something risky
else 
    echo "Let's stay boring"
fi

Диалоговый пакет по умолчанию устанавливается как минимум в SUSE Linux.

6 голосов
/ 12 декабря 2018

Вы можете использовать значение по умолчанию REPLY для read, преобразовать его в нижний регистр и сравнить с набором переменных с выражением.
Скрипт также поддерживает ja / si / oui

read -rp "Do you want a demo? [y/n/c] "

[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }

if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
   echo "Positive"
fi
6 голосов
/ 28 июня 2018

Только одно нажатие клавиши

Вот более длинный, но многократно используемый и модульный подход:

  • Возвращает 0 = да и 1 = нет
  • Не нужно нажимать ввод - только один символ
  • Можно нажать , ввести , чтобы принять выбор по умолчанию
  • Может отключить выбор по умолчанию для принудительного выбора
  • Работает для zsh и bash.

Значение по умолчанию "no" при нажатии enter

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

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?

Также обратите внимание, что [y/N]? был добавлен автоматически. По умолчанию «нет» принимается, поэтому ничего не отображается.

Повторно запрашивать, пока не будет дан правильный ответ:

$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *

Значение по умолчанию "yes" при нажатии enter

Обратите внимание, что Y пишется с заглавной буквы:

$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *

Выше я только что нажал клавишу ввода, и команда выполнилась.

Нет значения по умолчанию введите - требуется y или n

$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1

Здесь 1 или false было возвращено. Обратите внимание, что с помощью этой функции более низкого уровня вам нужно будет предоставить собственную подсказку [y/n]?.

Код

# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
  local REPLY IFS=
  >/dev/tty printf '%s' "$*"
  [[ $ZSH_VERSION ]] && read -rk1  # Use -u0 to read from STDIN
  # See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
  [[ $BASH_VERSION ]] && </dev/tty read -rn1
  printf '%s' "$REPLY"
}

# Get a y/n from the user, return yes=0, no=1 enter=$2
# Prompt using $1.
# If set, return $2 on pressing enter, useful for cancel or defualting
function get_yes_keypress {
  local prompt="${1:-Are you sure [y/n]? }"
  local enter_return=$2
  local REPLY
  # [[ ! $prompt ]] && prompt="[y/n]? "
  while REPLY=$(get_keypress "$prompt"); do
    [[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
    case "$REPLY" in
      Y|y)  return 0;;
      N|n)  return 1;;
      '')   [[ $enter_return ]] && return "$enter_return"
    esac
  done
}

# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
  local prompt="${*:-Are you sure} [y/N]? "
  get_yes_keypress "$prompt" 1
}    

# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
  local prompt="${*:-Are you sure} [Y/n]? "
  get_yes_keypress "$prompt" 0
}
4 голосов
/ 08 января 2015

Вдохновленный ответами @Mark и @Myrddin, я создал эту функцию для универсального приглашения

uniprompt(){
    while true; do
        echo -e "$1\c"
        read opt
        array=($2)
        case "${array[@]}" in  *"$opt"*) eval "$3=$opt";return 0;; esac
        echo -e "$opt is not a correct value\n"
    done
}

используйте это так:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
4 голосов
/ 08 декабря 2016

Я заметил, что никто не опубликовал ответ, показывающий многострочное эхо-меню для такого простого пользовательского ввода, поэтому вот мое мнение:

#!/bin/bash

function ask_user() {    

echo -e "
#~~~~~~~~~~~~#
| 1.) Yes    |
| 2.) No     |
| 3.) Quit   |
#~~~~~~~~~~~~#\n"

read -e -p "Select 1: " choice

if [ "$choice" == "1" ]; then

    do_something

elif [ "$choice" == "2" ]; then

    do_something_else

elif [ "$choice" == "3" ]; then

    clear && exit 0

else

    echo "Please select 1, 2, or 3." && sleep 3
    clear && ask_user

fi
}

ask_user

Этот метод был опубликован в надежде, что кто-то найдет его полезным и экономящим время.

4 голосов
/ 28 декабря 2013

Версия с множественным выбором:

ask () {                        # $1=question $2=options
    # set REPLY
    # options: x=..|y=..
    while $(true); do
        printf '%s [%s] ' "$1" "$2"
        stty cbreak
        REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
        stty -cbreak
        test "$REPLY" != "$(printf '\n')" && printf '\n'
        (
            IFS='|'
            for o in $2; do
                if [ "$REPLY" = "${o%%=*}" ]; then
                    printf '\n'
                    break
                fi
            done
        ) | grep ^ > /dev/null && return
    done
}

Пример:

$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$

Он установит REPLY в y (внутри скрипта).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...