Desejo pausar a entrada em um script de shell e solicitar opções ao usuário.
A pergunta padrão Yes
, No
ou Cancel
tipo.
Como faço isso em um prompt típico do bash?
read
comando para prompt
Desejo pausar a entrada em um script de shell e solicitar opções ao usuário.
A pergunta padrão Yes
, No
ou Cancel
tipo.
Como faço isso em um prompt típico do bash?
read
comando para prompt
Respostas:
O método mais simples e amplamente disponível para obter entrada do usuário em um prompt do shell é o read
comando A melhor maneira de ilustrar seu uso é uma demonstração simples:
while true; do
read -p "Do you wish to install this program?" yn
case $yn in
[Yy]* ) make install; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
Outro método, apontado por Steven Huwig , é o select
comando de Bash . Aqui está o mesmo exemplo usando select
:
echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
case $yn in
Yes ) make install; break;;
No ) exit;;
esac
done
Com select
você, não é necessário limpar a entrada - ela exibe as opções disponíveis e você digita um número correspondente à sua escolha. Também faz loops automaticamente, portanto, não há necessidade de um while true
loop tentar novamente se eles fornecerem entradas inválidas.
Além disso, Léa Gris demonstrou uma maneira de tornar a linguagem de solicitação agnóstica em sua resposta . A adaptação do meu primeiro exemplo para melhor atender a vários idiomas pode ser assim:
set -- $(locale LC_MESSAGES)
yesptrn="$1"; noptrn="$2"; yesword="$3"; noword="$4"
while true; do
read -p "Install (${yesword} / ${noword})? " yn
case $yn in
${yesptrn##^} ) make install; break;;
${noptrn##^} ) exit;;
* ) echo "Answer ${yesword} / ${noword}.";;
esac
done
Obviamente, outras strings de comunicação permanecem sem tradução aqui (Instalação, Resposta), que precisariam ser tratadas em uma tradução mais completa, mas mesmo uma tradução parcial seria útil em muitos casos.
Por fim, confira a excelente resposta de F. Hauri .
exit
para break
manter-se de fechar a guia quando eu selecionei 'não'.
break
no select
se não houver loop?
Dependendo
e se você quiser
Você pode usar o read
comando, seguido por if ... then ... else
:
echo -n "Is this a good question (y/n)? "
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo Yes
else
echo No
fi
(Obrigado ao comentário de Adam Katz : Substituído o teste acima por um que seja mais portátil e evite um garfo :)
Mas se você não quiser que o usuário acerte Return, escreva:
( Editado: como o @JonathanLeffler sugere, salvar a configuração do stty pode ser melhor do que simplesmente forçá-lo a sane .)
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
Nota: Isso foi testado emsh, bater, ksh, traço e busybox!
Mesmo, mas esperando explicitamente por you n:
#/bin/sh
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
Existem muitas ferramentas que foram construídos usando libncurses
, libgtk
, libqt
ou outras bibliotecas gráficas. Por exemplo, usando whiptail
:
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
Dependendo do seu sistema, pode ser necessário substituí-lo whiptail
por outra ferramenta similar:
dialog --yesno "Is this a good question" 20 60 && echo Yes
gdialog --yesno "Is this a good question" 20 60 && echo Yes
kdialog --yesno "Is this a good question" 20 60 && echo Yes
onde 20
é a altura da caixa de diálogo em número de linhas e a 60
largura da caixa de diálogo. Todas essas ferramentas têm quase a mesma sintaxe.
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
y|Y )
echo Yes
;;
* )
echo No
;;
esac
Eu prefiro usar case
para testar yes | ja | si | oui
se necessário ...
Sob bash, podemos especificar o comprimento da entrada pretendida para o read
comando:
read -n 1 -p "Is this a good question (y/n)? " answer
Em bash, o read
comando aceita um parâmetro de tempo limite , que pode ser útil.
read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes" # if 'yes' have to be default choice
Caixas de diálogo mais sofisticadas, além de yes - no
propósitos simples :
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
Barra de progresso:
dialog --gauge "Filling the tank" 20 60 0 < <(
for i in {1..100};do
printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
sleep .033
done
)
Pequena demonstração:
#!/bin/sh
while true ;do
[ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
whiptail "dialog boxes from shell scripts" >/dev/tty \
dialog "dialog boxes from shell with ncurses" \
gdialog "dialog boxes from shell with Gtk" \
kdialog "dialog boxes from shell with Kde" ) || exit
clear;echo "Choosed: $DIALOG."
for i in `seq 1 100`;do
date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
sleep .0125
done | $DIALOG --gauge "Filling the tank" 20 60 0
$DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
sleep 3
if $DIALOG --yesno "Do you like this demo?" 20 60 ;then
AnsYesNo=Yes; else AnsYesNo=No; fi
AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
$DIALOG --textbox /etc/motd 20 60
AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
Correct "This demo is useful" off \
Fun "This demo is nice" off \
Strong "This demo is complex" on 2>&1 >/dev/tty)
AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
" -1" "Downgrade this answer" off \
" 0" "Not do anything" on \
" +1" "Upgrade this anser" off 2>&1 >/dev/tty)
out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
$DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
done
Mais amostra? Veja Usando o chicote para escolher o dispositivo USB e o seletor de armazenamento removível USB: USBKeyChooser
Exemplo:
#!/bin/bash
set -i
HISTFILE=~/.myscript.history
history -c
history -r
myread() {
read -e -p '> ' $1
history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6
while myread line;do
case ${line%% *} in
exit ) break ;;
* ) echo "Doing something with '$line'" ;;
esac
done
Isto irá criar um arquivo .myscript.history
em seu $HOME
diretório, que você pode usar comandos de história do readline, como Up, Down, Ctrl+ routros e.
stty
fornece a -g
opção de uso: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty"
. Isso restaura a configuração exatamente como foi encontrada, que pode ou não ser a mesma que stty -sane
.
read answer
interpretará as barras invertidas antes dos espaços e das linhas e, de outra forma, as removerá, o que raramente é planejado. Use em read -r answer
vez disso, conforme SC2162 .
case
POSIX e o bash (use uma condição curinga em vez de uma substring do bash:) case $answer in; [Yy]* ) echo Yes ;;
, mas prefiro usar uma instrução condicional, favorecendo [ "$answer" != "${answer#[Yy]}" ]
a sua echo "$answer" | grep -iq ^y
. É mais portátil (alguns greps não-GNU não implementam -q
corretamente) e não possui a chamada de sistema. ${answer#[Yy]}
usa expansão de parâmetro para remover Y
ou y
do início de $answer
, causando uma desigualdade quando uma delas está presente. Isso funciona em qualquer shell POSIX (traço, ksh, bash, zsh, busybox, etc).
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Você pode usar o comando de leitura interno; Use a -p
opção para solicitar ao usuário uma pergunta.
Desde o BASH4, agora você pode usar -i
para sugerir uma resposta:
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH
(Mas lembre-se de usar a opção "readline" -e
para permitir a edição de linha com as teclas de seta)
Se você deseja uma lógica "sim / não", pode fazer algo assim:
read -e -p "
List the content of your home dir ? [Y/n] " YN
[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
FILEPATH
é o nome da variável que você escolheu e é definido com a resposta no prompt de comando. Portanto, se você executasse vlc "$FILEPATH"
, por exemplo, vlc
abriria esse arquivo.
-e
segundo exemplo (simples sim / não)?
-e -p
vez de -ep
?
-e
sinalizador / opção, você pode (dependendo da implementação) não conseguir digitar "y" e depois mudar de idéia e substituí-lo por um "n" (ou qualquer outra coisa a esse respeito); Ao documentar um comando, listar as opções separadamente é melhor para legibilidade / clareza, entre outros motivos.
O Bash selecionou para esse fim.
select result in Yes No Cancel
do
echo $result
done
exit
interior :)
Ctrl-D
Mas é claro, o código real usando ele vai precisar de uma pausa ou uma saída no corpo..)
exit
vai sair do script todos juntos, break
só vai sair do loop você está no (se você estiver em um while
ou case
circular)
Aqui está uma coisa que eu montei:
#!/bin/sh
promptyn () {
while true; do
read -p "$1 " yn
case $yn in
[Yy]* ) return 0;;
[Nn]* ) return 1;;
* ) echo "Please answer yes or no.";;
esac
done
}
if promptyn "is the sky blue?"; then
echo "yes"
else
echo "no"
fi
Sou iniciante, então leve isso com um pouco de sal, mas parece funcionar.
case $yn in
para case ${yn:-$2} in
, em seguida, você pode usar o segundo argumento como o valor padrão, Y ou N.
case $yn
para case "${yn:-Y}"
ter sim como padrão
inquire () {
echo -n "$1 [y/n]? "
read answer
finish="-1"
while [ "$finish" = '-1' ]
do
finish="1"
if [ "$answer" = '' ];
then
answer=""
else
case $answer in
y | Y | yes | YES ) answer="y";;
n | N | no | NO ) answer="n";;
*) finish="-1";
echo -n 'Invalid response -- please reenter:';
read answer;;
esac
fi
done
}
... other stuff
inquire "Install now?"
...
do_xxxx=y # In batch mode => Default is Yes
[[ -t 0 ]] && # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]] # Do if 'y' or 'Y' or empty
then
xxxx
fi
[[ -t 0 ]] && read ...
=> Chamar comando read
se TTYread -n 1
=> Aguarde um caractere$'\e[1;32m ... \e[0m '
=> Imprimir em verde [[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash regexdo_xxxx=y
[[ -t 0 ]] && { # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx || # read 'fails' on timeout
do_xxxx=n ; } # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
xxxx
fi
A maneira mais fácil de conseguir isso com o menor número de linhas é a seguinte:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
Este if
é apenas um exemplo: você decide como lidar com essa variável.
Use o read
comando:
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
e então todas as outras coisas que você precisa
Esta solução lê um único caractere e chama uma função em uma resposta sim.
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
echo
para ver por si mesmo.
Para obter uma boa caixa de entrada semelhante a ncurses, use a caixa de diálogo de comando assim:
#!/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
O pacote de diálogo é instalado por padrão pelo menos com o SUSE Linux. Parece:
read -e -p "Enter your choice: " choice
A -e
opção permite que o usuário edite a entrada usando as teclas de seta.
Se você deseja usar uma sugestão como entrada:
read -e -i "yes" -p "Enter your choice: " choice
-i
A opção imprime uma entrada sugestiva.
-e
-i
não funcionam no sh (Bourne shell), mas a questão é o bash marcado especificamente ..
Você pode usar o padrão REPLY
em a read
, converter em minúscula e comparar com um conjunto de variáveis com uma expressão.
O script também suporta 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
É possível manipular uma escolha "Sim / Não" com reconhecimento de localidade em um shell POSIX; usando as entradas da LC_MESSAGES
categoria localidade, o witch fornece padrões RegEx prontos para corresponder a uma entrada e cadeias de caracteres localizadas Sim Não.
#!/usr/bin/env sh
# Getting LC_MESSAGES values into variables
# shellcheck disable=SC2046 # Intended IFS splitting
IFS='
' set -- $(locale LC_MESSAGES)
yesexpr="$1"
noexpr="$2"
yesstr="$3"
nostr="$4"
messages_codeset="$5" # unused here, but kept as documentation
# Display Yes / No ? prompt into locale
echo "$yesstr / $nostr ?"
# Read answer
read -r yn
# Test answer
case "$yn" in
# match only work with the character class from the expression
${yesexpr##^}) echo "answer $yesstr" ;;
${noexpr##^}) echo "answer $nostr" ;;
esac
EDIT: Como @Urhixidur mencionado em seu comentário :
Infelizmente, o POSIX especifica apenas os dois primeiros (yesexpr e noexpr). No Ubuntu 16, yesstr e nostr estão vazios.
Consulte: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
LC_MESSAGES
As palavras-chave
yesstr
enostr
locale e os itensYESSTR
eNOSTR
langinfo foram usados anteriormente para corresponder às respostas afirmativas e negativas do usuário. Em POSIX.1-2008, oyesexpr
,noexpr
,YESEXPR
, eNOEXPR
expressões regulares estendidas substituíram-los. Os aplicativos devem usar os recursos gerais de mensagens com base no código do idioma para emitir mensagens de prompt que incluem respostas desejadas de amostra.
Como alternativa, use localidades da maneira Bash:
#!/usr/bin/env bash
IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES)
printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr"
printf -v prompt $"Please answer Yes (%s) or No (%s): " "$yesexpr" "$noexpr"
declare -- answer=;
until [[ "$answer" =~ $yes_or_no_regex ]]; do
read -rp "$prompt" answer
done
if [[ -n "${BASH_REMATCH[1]}" ]]; then
echo $"You answered: Yes"
else
echo $"No, was your answer."
fi
A resposta é correspondida usando os regexps fornecidos pelo ambiente de localidade.
Para converter as mensagens restantes, use bash --dump-po-strings scriptname
para gerar as seqüências de caracteres po para localização:
#: scriptname:8
msgid "Please answer Yes (%s) or No (%s): "
msgstr ""
#: scriptname:17
msgid "You answered: Yes"
msgstr ""
#: scriptname:19
msgid "No, was your answer."
msgstr ""
yesexpr
e noexpr
em um ambiente shell é usá-lo na correspondência RegEx específica do Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Aqui está uma abordagem mais longa, mas reutilizável e modular:
0
= sim e 1
= nãozsh
e bash
.Observe que o N
capital é maiúsculo. Aqui, enter é pressionado, aceitando o padrão:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
Observe também que [y/N]?
foi anexado automaticamente. O "não" padrão é aceito, então nada é ecoado.
Solicite novamente até que uma resposta válida seja fornecida:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
Observe que o Y
é maiúsculo:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Acima, eu apenas pressionei enter, então o comando foi executado.
y
oun
$ 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
Aqui, 1
ou false foi retornado. Observe que, com esta função de nível inferior, você precisará fornecer seu próprio [y/n]?
prompt.
# 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
}
Show dangerous command [y/N]? [y/n]?
eShow dangerous command [Y/n]? [y/n]?
Desculpe por postar em um post tão antigo. Algumas semanas atrás, eu estava enfrentando um problema semelhante, no meu caso, precisava de uma solução que também funcionasse dentro de um script de instalação online, por exemplo:curl -Ss https://raw.github.com/_____/installer.sh | bash
Usar read yesno < /dev/tty
funciona bem para mim:
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
Espero que isso ajude alguém.
tty
entradas como você teria feito também para você, e também ter recebido loop de entrada ruim (imagine alguns caracteres no buffer; seu método forçaria o usuário a sempre escolher não).
Notei que ninguém postou uma resposta mostrando o menu de eco de várias linhas para uma entrada tão simples do usuário, então aqui está a minha tentativa:
#!/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
Este método foi publicado na esperança de que alguém possa achar útil e que economiza tempo.
Versão de múltipla escolha:
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
}
Exemplo:
$ 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
$
Ele será definido REPLY
como y
(dentro do script).
Eu sugiro que você use o diálogo ...
Aprendiz do Linux: melhore os scripts do Bash Shell usando o diálogo
O comando dialog permite o uso de caixas de janela em shell scripts para tornar seu uso mais interativo.
é simples e fácil de usar, há também uma versão do gnome chamada gdialog que usa exatamente os mesmos parâmetros, mas mostra o estilo da GUI no X.
Inspirado pelas respostas de @Mark e @Myrddin, criei esta função para um prompt universal
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
}
use-o assim:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
mais genérico seria:
function menu(){
title="Question time"
prompt="Select:"
options=("Yes" "No" "Maybe")
echo "$title"
PS3="$prompt"
select opt in "${options[@]}" "Quit/Cancel"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
return
}
Uma maneira simples de fazer isso é com xargs -p
ou gnu parallel --interactive
.
Eu gosto do comportamento do xargs um pouco melhor para isso, porque ele executa cada comando imediatamente após o prompt, como outros comandos unix interativos, em vez de coletar os yesses para executar no final. (Você pode pressionar Ctrl-C depois de passar pelos que deseja.)
por exemplo,
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
xargs --interactive
é limitado a sim ou não. Contanto que seja tudo o que você precisa, isso pode ser suficiente, mas minha pergunta original deu um exemplo com três resultados possíveis. Eu realmente gosto que seja fácil de usar; muitos cenários comuns se beneficiariam de sua capacidade de ser canalizado.
Como amigo de um comando de uma linha, usei o seguinte:
while [ -z $prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) prompt=true; break;; n|N ) exit 0;; esac; done; prompt=;
Longform escrito, funciona assim:
while [ -z $prompt ];
do read -p "Continue (y/n)?" choice;
case "$choice" in
y|Y ) prompt=true; break;;
n|N ) exit 0;;
esac;
done;
prompt=;
Eu usei a case
declaração algumas vezes nesse cenário, usar a declaração de caso é uma boa maneira de fazer isso. Um while
loop, que ecapsula o case
bloco, que utiliza uma condição booleana, pode ser implementado para manter ainda mais controle do programa e atender a muitos outros requisitos. Após todas as condições terem sido atendidas, break
pode ser usado um que passará o controle de volta para a parte principal do programa. Além disso, para atender a outras condições, é claro que instruções condicionais podem ser adicionadas para acompanhar as estruturas de controle: case
instrução e while
loop possível .
Exemplo de uso de uma case
declaração para atender sua solicitação
#! /bin/sh
# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-shell, e.g. /bin/sh
# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input
# of the prompt in a case statement (case control structure),
echo Would you like us to perform the option: "(Y|N)"
read inPut
case $inPut in
# echoing a command encapsulated by
# backticks (``) executes the command
"Y") echo `Do something crazy`
;;
# depending on the scenario, execute the other option
# or leave as default
"N") echo `execute another option`
;;
esac
exit
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=''
echo -n "> $message (Yes/No/Cancel) " >&2
while [ -z "$result" ] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result='Y' ;;
n|N ) result='N' ;;
c|C ) result='C' ;;
esac
done
echo $result
}
case $(@confirm 'Confirm?') in
Y ) echo "Yes" ;;
N ) echo "No" ;;
C ) echo "Cancel" ;;
esac
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=3
echo -n "> $message (y/n) " >&2
while [[ $result -gt 1 ]] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result=0 ;;
n|N ) result=1 ;;
esac
done
return $result
}
if @confirm 'Confirm?' ; then
echo "Yes"
else
echo "No"
fi
yn() {
if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
then eval $1;
else eval $2;
fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'
yn(){ read -s -n 1 -p '[y/n]'; test "$REPLY" = "y" ; } yn && echo success || echo failure
Em resposta a outros:
Você não precisa especificar maiúsculas e minúsculas no BASH4, basta usar o ',,' para fazer uma var minúscula. Também não gosto de colocar código dentro do bloco de leitura, obter o resultado e lidar com ele fora do bloco de leitura IMO. Inclua também um 'q' para sair do IMO. Por fim, por que digite 'yes' basta usar -n1 e pressionar y.
Exemplo: o usuário pode pressionar y / ne também q para sair.
ans=''
while true; do
read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
case ${ans,,} in
y|n|q) break;;
*) echo "Answer y for yes / n for no or q for quit.";;
esac
done
echo -e "\nAnswer = $ans"
if [[ "${ans,,}" == "q" ]] ; then
echo "OK Quitting, we will assume that he is"
exit 0
fi
if [[ "${ans,,}" == "y" ]] ; then
echo "MikeQ is the greatest!!"
else
echo "No? MikeQ is not the greatest?"
fi
Na maioria das vezes, nesses cenários, você precisa continuar executando o script até que o usuário continue digitando "yes" e só precise parar quando o usuário digitar "no". O trecho abaixo ajudaria você a conseguir isso!
#!/bin/bash
input="yes"
while [ "$input" == "yes" ]
do
echo "execute script functionality here..!!"
echo "Do you want to continue (yes/no)?"
read input
done
[yn]
opção, a que está em maiúscula é o padrão, ou seja, o padrão é[Yn]
"yes" e o[yN]
"no". Veja ux.stackexchange.com/a/40445/43532