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.