Melhor maneira de aceitar variações de 'Sim' em um prompt de shell


27

O teste de usabilidade de um script de shell que escrevi descobriu que as pessoas tinham expectativas diferentes sobre como responder a uma pergunta que esperava 'sim' como resposta. Veja variações no exemplo de código abaixo.

Certamente deve haver uma maneira melhor do que eu inventei? Qual é a sua forma legível e mais curta sobre isso?

read -p 'Answer this question with yes: ' answer
if [ "$answer" = 'Y'
  -o "$answer" = 'YES'
  -o "$answer" = 'Yes'
  -o "$answer" = 'y'
  -o "$answer" = 'yes'
  -o some-alternate-condition ]; then

  echo 'Surely this can be written better?'
fi

2
Votou para fechar. Embora eu esteja interessado na questão, provavelmente é mais uma questão de programação, portanto deve estar no SO.
Phllhehe

A resposta de programação pode ser algo como Bash: Verifique se elemento do array existe
phunehehe

3
@phunehehe: Não concordo em mudar para SO, não apenas porque temos um histórico de aceitar programação de shell, mas também porque não é apenas uma questão de como fazê-lo, mas também uma pergunta sobre qual deve ser a especificação.
Gilles 'SO- stop be evil'

4
Eu escrevi um script muito parecido com isso uma vez. Em seguida, o programa foi traduzido para o francês e chinês simplificado. I desnatado a versão francesa e vi meu alerta foi traduzido para "Enter oui ou non" mas é claro que o código ainda queria "Y *" ou "N *"
Ben Jackson

Respostas:


15

Usar a caseé um tanto equivalente, mas não perfeito, pois declarações como YEsão aceitas.

read -p 'Answer this question with yes: ' answer
case "${answer}" in
    [yY]|[yY][eE][sS])
        echo 'Surely this can be written better?' ;;
esac

3
Eu diria que a intenção do usuário é bastante clara para 'ye'.
Aeyoun

48

O padrão UNIX fornece um exemplo de código para isso usando o localeutilitário :

if printf "%s\n" "$response" | grep -Eq "$(locale yesexpr)"
then
    affirmative processing goes here
else
    non-affirmative processing goes here
fi

O valor para 'yesexpr' no código do POSIXidioma (e nos idiomas inglês em sistemas reais) é "^[yY]". Deve ser interpretado como uma expressão regular estendida. Veja também noexpr.


11
Agradável. Mas eu pareço ser um idiota. Onde posso encontrar uma lista dos argumentos que você localeconhece? A página de manual na minha caixa do Mac OS 10.5 parece não ter.
dmckee

Agradável. Poderia, por favor, ligar de volta à fonte?
Aeyoun 22/05

3
@ dmckee você pode fazer locale -k LC_MESSAGES(e para o outro LC_whatever), ou veja aqui os definidos pelo padrão. @ Daniel Qual fonte, além da página do utilitário de localidade que eu vinculei?
Random832

11
Ótima resposta, definitivamente deve ser a aceita.
Jlliagre

6

Permanecendo no bash (ou em qualquer outro shell, se você exibir o prompt independentemente):

case $answer in
  [Yy]*) echo Ok;;
  *) echo "Can't you read? I said to say yes.";;
esac

Este aceita respostas como yncomo Sim,  y(com um espaço inicial) como não, e wlkjzuhfodcomo não, o que pode não ser o ideal, mas é consistente com prompts de shell típicos: é assim rm -i, find -oke outros fazê-lo.

Isso evita toda a questão da internacionalização: em outros idiomas, você precisaria traduzir as respostas esperadas. Não há método shell padrão então; você pode ativar a caixa de diálogo , mas seu script exigirá que seja instalado (está disponível em muitas distribuições, mas nem sempre é instalado por padrão).

if dialog --yesno "Choose yes" 0 0; then 

3

Eu costumo usar uma função simples:

Confirm() { read -sn 1 -p "$* [Y/N]? "; [[ ${REPLY:0:1} = [Yy] ]]; }

A função apenas retorna 0se You yé inserida e 1se qualquer outra coisa é inserida. Pode ser usado com if...fi:

if Confirm "Type y or n"; then
echo "You typed y"
else
echo "You typed n"
fi

Ou assim:

Confirm "Type y" && echo "You typed y"

Tire o -spara ter uma história visual do que foi digitado.
Tom Hale

0

Apenas re-modificado @faif ans

YesOrNo() {
        while :
        do
                read -p 'Do you want to Continue (yes/no?): ' answer
                case "${answer}" in
                    [yY]|[yY][eE][sS]) exit 0 ;;
                        [nN]|[nN][oO]) exit 1 ;;
                esac
        done
}


if $( YesOrNo ); then
        echo "Ans is yes.. Do something....."
else
        echo "Ans is No... skip.."
fi

Teste

root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):  # if Blank Enter then ask again
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): no
Ans is No... skip..
root@ubuntu:~# bash confirm.sh
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?):
Do you want to Continue (yes/no?): ye
Do you want to Continue (yes/no?): yes
Ans is yes.. Do something.....
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.