В Bash, как добавить "Вы уверены, [Y/n]" для любой команды или псевдонима?

В этом конкретном случае я хотел бы добавить подтверждение в Bash для

Are you sure? [Y/n]

для Mercurial hg push ssh://[email protected]//somepath/morepath, который на самом деле является псевдонимом. Есть ли стандартная команда, которая может быть добавлена ​​в псевдоним для ее достижения?

Причина в том, что hg push и hg out могут звучать одинаково, а иногда, когда я хочу hgoutrepo, я могу случайно набрать hgpushrepo (оба являются псевдонимами).

Обновление:, если это может быть что-то вроде встроенной команды с другой командой, например: confirm && hg push ssh://..., что было бы здорово... просто команда, которая может запросить yes или no и продолжить с остальными, если yes.

Ответы

Ответ 1

Это более компактные и универсальные формы ответа Хэмиша. Они обрабатывают любую смесь букв верхнего и нижнего регистра:

read -r -p "Are you sure? [y/N] " response
case "$response" in
    [yY][eE][sS]|[yY]) 
        do_something
        ;;
    *)
        do_something_else
        ;;
esac

Или, для Bash >= версия 3.2:

read -r -p "Are you sure? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]
then
    do_something
else
    do_something_else
fi

Примечание. Если $response - пустая строка, это приведет к ошибке. Чтобы исправить, просто добавьте кавычки: "$response". - Всегда используйте двойные кавычки в переменных, содержащих строки (например: предпочитаете использовать "[email protected]" вместо [email protected]).

Или, Bash 4.x:

read -r -p "Are you sure? [y/N] " response
response=${response,,}    # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...

Edit:

В ответ на ваше редактирование здесь, как вы должны создать и использовать команду confirm на основе первой версии в моем ответе (она будет работать аналогично двум другим):

confirm() {
    # call with a prompt string or use a default
    read -r -p "${1:-Are you sure? [y/N]} " response
    case "$response" in
        [yY][eE][sS]|[yY]) 
            true
            ;;
        *)
            false
            ;;
    esac
}

Чтобы использовать эту функцию:

confirm && hg push ssh://..

или

confirm "Would you really like to do a push?" && hg push ssh://..

Ответ 2

Вот примерно фрагмент, который вы хотите. Позвольте мне узнать, как перенаправить аргументы.

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt == "y" || $prompt == "Y" || $prompt == "yes" || $prompt == "Yes" ]]
then
  # http://stackoverflow.com/questions/1537673/how-do-i-forward-parameters-to-other-command-in-bash-script
else
  exit 0
fi

Следите за yes | command name here:)

Ответ 3

Чтобы избежать явной проверки этих вариантов "да", вы можете использовать оператор регулярного выражения bash '= ~' с регулярным выражением:

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt =~ [yY](es)* ]]
then
(etc...)

Это проверяет, начинается ли ввод пользователя с 'y' или 'Y', за которым следуют ноль или более. es.

Ответ 4

Подтверждения легко обойти с возвратом каретки, и мне посчастливилось постоянно запрашивать действительный ввод.

Здесь функция, чтобы сделать это легко. "Недействительный ввод" отображается красным цветом, если Y | N не получен, и пользователь снова запрашивается.

prompt_confirm() {
  while true; do
    read -r -n 1 -p "${1:-Continue?} [y/n]: " REPLY
    case $REPLY in
      [yY]) echo ; return 0 ;;
      [nN]) echo ; return 1 ;;
      *) printf " \033[31m %s \n\033[0m" "invalid input"
    esac 
  done  
}

# example usage
prompt_confirm "Overwrite File?" || exit 0

Вы можете изменить приглашение по умолчанию, передав аргумент

Ответ 5

Это может быть взлом:

как в вопросе В Unix/ Bash, is "xargs -p" хороший способ запросить подтверждение перед запуском любой команды?

мы можем использовать xargs для выполнения задания:

echo ssh://[email protected]//somepath/morepath | xargs -p hg push

конечно, это будет установлено как псевдоним, например hgpushrepo

Пример:

$ echo foo | xargs -p ls -l
ls -l foo?...y
-rw-r--r--  1 mikelee    staff  0 Nov 23 10:38 foo

$ echo foo | xargs -p ls -l
ls -l foo?...n

$

Ответ 6

Добавьте в файл /etc/bashrc следующее. Этот script добавляет резидентную "функцию" вместо псевдонима, называемого "подтвердить".


function confirm( )
{
#alert the user what they are about to do.
echo "About to [email protected]";
#confirm with the user
read -r -p "Are you sure? [Y/n]" response
case "$response" in
    [yY][eE][sS]|[yY]) 
              #if yes, then execute the passed parameters
               "[email protected]"
               ;;
    *)
              #Otherwise exit...
              echo "ciao..."
              exit
              ;;
esac
}

Ответ 7

read -r -p "Are you sure? [Y/n]" response
  response=${response,,} # tolower
  if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
      your-action-here
  fi

Ответ 8

Ну, вот моя версия confirm, модифицированная от версии Джеймса:

function confirm() {
  local response msg="${1:-Are you sure} (y/[n])? "; shift
  read -r $* -p "$msg" response || echo
  case "$response" in
  [yY][eE][sS]|[yY]) return 0 ;;
  *) return 1 ;;
  esac
}

Эти изменения:

  1. использовать local чтобы предотвратить совпадение имен переменных
  2. read используйте $2 $3... чтобы контролировать его действие, так что вы можете использовать -n и -t
  3. если read завершилось неудачно, echo перевод строки для красоты
  4. мой Git on Windows имеет только bash-3.1 и не имеет true или false, поэтому используйте return. Конечно, это также совместимо с bash-4.4 (текущим в Git для Windows).
  5. используйте IPython-стиль "(y/[n])", чтобы четко указать, что "n" является значением по умолчанию.

Ответ 9

Это может быть немного слишком коротким, но для моего личного использования, это прекрасно работает

read -n 1 -p "Push master upstream? [Y/n] " reply; 
if [ "$reply" != "" ]; then echo; fi
if [ "$reply" = "${reply#[Nn]}" ]; then
    git push upstream master
fi

read -n 1 только читает один символ. Не нужно нажимать ввод. Если это не "n" или "N", предполагается, что это "Y". Простое нажатие клавиши ввода также означает Y.

(что касается настоящего вопроса: создайте сценарий bash и измените псевдоним так, чтобы он указывал на этот сценарий, а не на то, на что он указывал ранее)

Ответ 10

Поздно к игре, но я создал еще один вариант функций confirm предыдущих ответов:

confirm ()
{
    read -r -p "$(echo [email protected]) ? [y/N] " YESNO

    if [ "$YESNO" != "y" ]; then
        echo >&2 "Aborting"
        exit 1
    fi

    CMD="$1"
    shift

    while [ -n "$1" ]; do
        echo -en "$1\0"
        shift
    done | xargs -0 "$CMD" || exit $?
}

Чтобы использовать его:

confirm your_command

Особенности:

  • выводит вашу команду как часть приглашения
  • передает аргументы с помощью разделителя NULL
  • сохраняет состояние выхода вашей команды

Ошибка:

  • echo -en работает с bash, но может сбой в вашей оболочке
  • может завершиться ошибкой, если аргументы помешают echo или xargs
  • zillion другие ошибки, потому что shell-скрипты трудны.

Ответ 11

Попробуйте,

 #!/bin/bash
 pause ()
 {
 REPLY=Y
 while [ "$REPLY" == "Y" ] || [ "$REPLY" != "y" ]
 do
  echo -e "\t\tPress 'y' to continue\t\t\tPress 'n' to quit"
  read -n1 -s
      case "$REPLY" in
      "n")  exit                      ;;
      "N")  echo "case sensitive!!"   ;; 
      "y")  clear                     ;;
      "Y")  echo "case sensitive!!"   ;;
      * )  echo "$REPLY is Invalid Option"     ;;
 esac
 done
 }
 pause
 echo "Hi"

Ответ 12

Не нужно нажимать ввод

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

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

По умолчанию "нет" при нажатии 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 *

По умолчанию "да" при нажатии Enter

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

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

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

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

$ get_yes_keypress "Here you cannot press enter. Do you like this"
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]? нет заглавных букв [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
}

Ответ 13

Это не значит "просить" да "или" нет ", но просто взломать: псевдоним hg push ... не hgpushrepo, а <<22 > , и к тому моменту, когда я могу изложить все это, мозг сделал логический выбор.

Ответ 14

Не то же самое, но идея, которая работает в любом случае.

#!/bin/bash  
i='y'  
while [ ${i:0:1} != n ]  
do  
    # Command(s)  
    read -p " Again? Y/n " i  
    [[ ${#i} -eq 0 ]] && i='y'  
done  

Вывод:
   Еще раз? Y/n N
   Еще раз? Y/n Все, что угодно    Еще раз? Y/n 7
   Еще раз? Y/n &
   Еще раз? Y/n nsijf
$

Теперь проверяется только 1-й символ $i.

Ответ 15

Ниже код объединяет две вещи

  • shopt -s nocasematch, который будет заботиться о нечувствительности к регистру

  • и если условие, которое примет как вход, либо вы передадите да, Да, YES, y.

    shopt -s nocasematch

    если [[sed-4.2.2. $LINE = ~ (да | y) $]]

    тогда выход 0

    ц

Ответ 16

Вот мое решение, которое использует локализованное регулярное выражение. Так что на немецком языке "j" для "Ja" будет интерпретироваться как "да" .

Первый аргумент - это вопрос, если вторым аргументом является "y", чем "да" будет ответом по умолчанию, иначе нет ответа по умолчанию. Возвращаемое значение равно 0, если ответ был "да" и 1, если ответ был "нет".

function shure(){
    if [ $# -gt 1 ] && [[ "$2" =~ ^[yY]*$ ]] ; then
        arg="[Y/n]"
        reg=$(locale noexpr)
        default=(0 1)
    else
        arg="[y/N]"
        reg=$(locale yesexpr)
        default=(1 0)
    fi
    read -p "$1 ${arg}? : " answer
    [[ "$answer" =~ $reg ]] && return ${default[1]} || return ${default[0]}
}

Вот базовое использование

# basic example default is no
shure "question message" && echo "answer yes" || echo "answer no"
# print "question message [y/N]? : "

# basic example default set to yes
shure "question message" y && echo "answer yes" || echo "answer no"
# print "question message [Y/n]? : "

Ответ 17

Эта версия позволяет вам иметь более одного дела y или Y, n или N

  1. Дополнительно: повторяйте вопрос до тех пор, пока не будет предоставлен вопрос для утверждения.

  2. По желанию: игнорировать любой другой ответ

  3. По желанию: выйдите из терминала, если хотите

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) break ;;        # exit case statement gracefully
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }
    

Обратите внимание и на это: в последней строке этой функции очистите переменную REPLY. В противном случае, если вы echo $REPLY увидите, что он все еще установлен, пока вы не откроете или не закроете свой терминал или не установите его снова.