Modo migliore di accettare variazioni di 'Sì' da un prompt della shell


27

I test di usabilità di uno script di shell che ho scritto hanno scoperto che le persone avevano aspettative diverse su come rispondere a una domanda che si aspettava "sì" come risposta. Vedi le varianti nell'esempio di codice seguente.

Sicuramente ci deve essere un modo migliore di quello che mi è venuto in mente? Qual è la tua forma leggibile e più breve su questo?

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
Votato per chiudere. Mentre sono interessato alla domanda, probabilmente è più una domanda di programmazione, quindi dovrebbe essere su SO.
phunehehe,

Una risposta di programmazione potrebbe essere qualcosa di simile a Bash: controlla se esiste un elemento array
phunehehe

3
@phunehehe: non sono d'accordo con il passaggio a SO, non solo perché abbiamo una storia di accettazione della programmazione della shell, ma anche perché non è solo una questione di come farlo, ma anche una questione di quali dovrebbero essere le specifiche.
Gilles 'SO- smetti di essere malvagio'

4
Ho scritto una sceneggiatura molto simile una volta. Quindi il programma è stato tradotto in francese e in cinese semplificato. Ho sfogliato la versione francese e ho visto che il mio prompt era tradotto in "Inserisci oui o non" ma ovviamente il codice voleva ancora "Y *" o "N *"
Ben Jackson,

Risposte:


15

L'uso di a caseè in qualche modo equivalente ma non perfetto poiché YEsono accettate affermazioni come .

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

3
Direi che l'intento dell'utente è abbastanza chiaro da "voi".
Aeyoun,

48

Lo standard UNIX fornisce un codice di esempio per questo utilizzando l' localeutilità :

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

Il valore di 'yesexpr' nelle impostazioni POSIXlocali (e nelle versioni locali inglesi sui sistemi reali) è "^[yY]". Deve essere interpretato come un'espressione regolare estesa. Vedi anche noexpr.


1
Bello. Ma mi sembra un idiota. Dove posso trovare un elenco degli argomenti che localeconosce? La pagina man sulla mia scatola di Mac OS 10.5 non sembra averli.
dmckee,

Bello. Potresti ricollegarti alla fonte?
Aeyoun,

3
@dmckee puoi farlo locale -k LC_MESSAGES(e per l'altro LC_whatever), oppure vedere qui per quelli definiti dallo standard. @Daniel quale fonte diversa dalla pagina dell'utilità locale che ho collegato?
Casuale 832,

1
Ottima risposta, dovrebbe sicuramente essere quella accettata.
jlliagre,

6

Rimanere in bash (o qualsiasi altra shell se si visualizza il prompt in modo indipendente):

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

Questo accetta risposte come ynsì,  y(con uno spazio iniziale) come no, e wlkjzuhfodcome no, che potrebbe non essere ottimale ma è coerente con i tipici prompt della shell: ecco come rm -i, find -oke altri lo fanno.

Ciò evita l'intero problema dell'internazionalizzazione: in altre lingue, dovresti tradurre le risposte attese. Allora non esiste un metodo shell standard; puoi passare alla finestra di dialogo , ma poi lo script richiederà l'installazione (è disponibile in molte distribuzioni ma non sempre installato di default).

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

3

Di solito uso una semplice funzione:

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

La funzione restituisce semplicemente 0se si immette Yo se ysi immette 1qualcos'altro. Può essere utilizzato con if...fi:

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

O proprio così:

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

Decolla -sper avere una cronologia visiva di ciò che è stato digitato.
Tom Hale,

0

Ho appena modificato @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

Test

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.....
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.