Melhor maneira de aceitar variações de "Yes" de um prompt de shell

27

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

Certamente deve haver uma maneira melhor que o que eu inventei? Qual é o seu legível e forma mais curta assumir 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
    
por Aeyoun 22.05.2011 / 17:42

5 respostas

15

Usar case é um pouco equivalente, mas não perfeito, pois declarações como YE sã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
    
por 22.05.2011 / 17:57
48

O padrão UNIX fornece código de exemplo para isso usando o locale utility :

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

O valor de 'yesexpr' no POSIX locale (e em idiomas ingleses em sistemas reais) é "^[yY]" . Deve ser interpretado como uma expressão regular estendida. Veja também noexpr.

    
por 22.05.2011 / 20:37
6

Permanecendo no bash (ou 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

Isso aceita respostas como yn como sim,  y (com um espaço inicial) como não e wlkjzuhfod como não, o que pode não ser ideal, mas é consistente com prompts típicos do shell: é assim que rm -i , find -ok e outros fazem isso.

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

if dialog --yesno "Choose yes" 0 0; then …
    
por 22.05.2011 / 17:58
3

Eu costumo usar uma função simples:

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

A função apenas retorna 0 se Y ou y for inserido e 1 se qualquer outra coisa for 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 apenas assim:

Confirm "Type y" && echo "You typed y"
    
por 05.06.2011 / 11:29
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.....
    
por 16.09.2013 / 13:35