В Bash, как добавить "вы уверены [Y / n]" к любой команде или псевдониму?
в этом конкретном случае я хотел бы добавить подтверждение в Bash для
Are you sure? [Y/n]
для переменчивого по hg push ssh://username@www.example.com//somepath/morepath
, который фактически псевдоним. Есть ли стандартная команда, которая может быть добавлена в псевдоним для ее достижения?
причина в том, что hg push
и hg out
может звучать похоже, а иногда, когда я хочу hgoutrepo
, Я могу случайно ввести 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"
. - Всегда используйте двойные кавычки в переменных, содержащих строки (например: предпочитают использовать "$@"
вместо $@
).
Или, Bash 4.x:
read -r -p "Are you sure? [y/N] " response
response=${response,,} # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...
Edit:
в ответ на ваше редактирование, вот как вы создадите и используете
вот примерно фрагмент, который вы хотите. Позвольте мне выяснить, как продвигать аргументы.
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
, изменено из James ' one:
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-style" (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
характеристики:
- печатает вашу команду как часть подсказки
- передает Аргументы с помощью нулевого разделителя
- сохраняет состояние выхода вашей команды
ошибки:
-
echo -en
работает сbash
но, возможно, не в вашем Шелл!--15--> - может потерпеть неудачу, если аргументы мешать
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-только один символ
- нажать enter принять выбор по умолчанию
- можно отключить выбор по умолчанию, чтобы принудительно выбрать
- работы как
zsh
иbash
.
по умолчанию "нет" при нажатии enter
отметим, что N
это capitalsed. Здесь нажать 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, поэтому команда побежала.
нет значения по умолчанию 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-й символ $I read.
ниже код объединяет две вещи
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
на read -n 1
просто читает один символ. Если это не строчная буква "n", предполагается, что это "Y".
(что касается реального вопроса: сделайте это скриптом bash и измените свой псевдоним, чтобы указать на этот скрипт вместо того, на что указывал раньше)