В Bash, как добавить "вы уверены [Y / n]" в любую команду или псевдоним?
в данном конкретном случае, я хотел бы добавить подтверждение в Bash для
Are you sure? [Y/n]
для переменчивого по hg push ssh://username@www.example.com//somepath/morepath
, который на самом деле является псевдонимом. Есть ли стандартная команда, которая может быть добавлена в псевдоним для ее достижения?
причина в том, что hg push
и hg out
может звук, похожий и иногда, когда я хочу!--4-->, Я могу случайно ввести hgpushrepo
(оба являются псевдонимами).
обновление: если это может быть что-то вроде встроенной команды с другая команда, например:confirm && hg push ssh://...
это было бы здорово... просто команда, которая может попросить yes
или no
и продолжайте с остальными, если yes
.
16 ответов:
это более компактные и универсальные формы Хэмиша ответ. Они обрабатывают любую смесь прописных и строчных букв:
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"
. - Всегда используйте двойные кавычки в переменных, содержащих строки (например: prefer to use"$@"
вместо$@
).Или, Баш 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://..
вот примерно фрагмент, который вы хотите. Позвольте мне узнать, как аргументы.
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
:)
чтобы избежать явной проверки этих вариантов "да", вы можете использовать оператор регулярного выражения bash '=~' с регулярным выражением:
read -p "Are you sure you want to continue? <y/N> " prompt if [[ $prompt =~ [yY](es)* ]] then (etc...)
это проверяет, начинается ли пользовательский ввод с " y " или " Y "и сопровождается нулем или более" es.
подтверждения легко обходятся с возвратом каретки, и я считаю полезным постоянно запрашивать действительный ввод.
вот функция, чтобы сделать это легко. "недопустимый ввод" отображается красным цветом, если 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 " 3[31m %s \n3[0m" "invalid input" esac done } # example usage prompt_confirm "Overwrite File?" || exit 0
вы можете изменить приглашение по умолчанию, передав аргумент
это может быть Хак:
как в вопрос в Unix / Bash, является ли "xargs-p" хорошим способом запросить подтверждение перед запуском любой команды?
можно использовать
xargs
выполнить задание:echo ssh://username@www.example.com//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 $
добавьте в файл /etc/bashrc следующее. Этот скрипт добавляет резидентную " функцию "вместо псевдонима под названием"подтвердить".
function confirm( ) { #alert the user what they are about to do. echo "About to $@...."; #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 "$@" ;; *) #Otherwise exit... echo "ciao..." exit ;; esac }
read -r -p "Are you sure? [Y/n]" response response=${response,,} # tolower if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then your-action-here fi
Ну, вот моя версия
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 }
следующие изменения:
- использовать
local
чтобы предотвратить столкновение имен переменныхread
использовать...
для управления его действием, так что вы можете использовать-n
и-t
- если
read
завершается неудачно,echo
линия подачи для красоты- мой
Git on Windows
толькоbash-3.1
и нетtrue
илиfalse
, так что используйтеreturn
вместо. Конечно, это также совместимо с bash-4.4 (текущий в Git для Windows).- используйте стиль IPython " (y / [n])", чтобы четко указать, что "n" является значением по умолчанию.
поздно к игре, но я создал еще один вариант
confirm
функции предыдущих ответов:confirm () { read -r -p "$(echo $@) ? [y/N] " YESNO if [ "$YESNO" != "y" ]; then echo >&2 "Aborting" exit 1 fi CMD="" shift while [ -n "" ]; do echo -en "" shift done | xargs -0 "$CMD" || exit $? }
использовать:
confirm your_command
характеристики:
- выводит команду как часть приглашения
- передает Аргументы с помощью разделителя NULL
- сохраняет состояние выхода вашей команды
ошибки:
echo -en
работает сbash
но может потерпеть неудачу в вашем оболочка- может произойти сбой, если аргументы мешают
echo
илиxargs
- миллион других ошибок, потому что сценарий оболочки трудно
попробуйте
#!/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"
не требуется нажимать enter
вот более длинный, но многоразовый и модульный подход:
- возвращает
0
=да1
=не- не требуется нажимать enter - только один символ
- нажать введите принять выбор по умолчанию
- можно отключить выбор по умолчанию, чтобы заставить выбор
- работы как
zsh
иbash
.по умолчанию "нет" при нажатии enter
отметим, что
N
С большой буквы. Здесь нажать enter, по умолчанию:$ 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
is с большой буквы:$ 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]?
код
# 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= # Prompt using . # If set, return on pressing enter, useful for cancel or defualting function get_yes_keypress { local prompt="${1:-Are you sure} [y/n]? " local enter_return= 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 }
Не то же самое, но идея все равно работает.
#!/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 7
Опять? Y/n &
Опять? Y/n nsijf
$теперь только проверяет 1-й символ $я читал.
ниже код сочетает в себе две вещи
shopt-s nocasematch, который будет заботиться о нечувствительном к регистру
и если условие, которое будет принимать оба входа либо вы проходите да, да, да, y.
shopt-s nocasematch
Если [[ sed-4.2.2.$LINE = ~ (yes / y)$ ]]
затем выход 0
fi
вот мое решение, которое использует локализованное регулярное выражение. Поэтому в немецком языке также "j "для" Ja " будет интерпретироваться как да.
первый аргумент-это вопрос, если второй аргумент "y", то да будет ответом по умолчанию, иначе нет будет ответом по умолчанию. Возвращаемое значение равно 0, если ответ был "да" и 1, если ответ был "нет".
function shure(){ if [ $# -gt 1 ] && [[ "" =~ ^[yY]*$ ]] ; then arg="[Y/n]" reg=$(locale noexpr) default=(0 1) else arg="[y/N]" reg=$(locale yesexpr) default=(1 0) fi read -p " ${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]? : "
Это может быть немного слишком коротким, но для моего личного использования, он отлично работает
read -n 1 -p "Push master upstream? [Y/n] " reply; if [ "$reply" != "" ]; then echo; fi if [ "$reply" != "n" ]; then git push upstream master fi
The
read -n 1
просто читает один символ. Если это не строчная буква "n", предполагается, что это "Y".(что касается реального вопроса: сделайте это скриптом bash и измените свой псевдоним, чтобы указать на этот скрипт вместо того, на что он указывал раньше)