Lepszy sposób akceptowania odmian „Tak” z zachęty powłoki


27

Testy użyteczności skryptu powłoki, który napisałem, wykazały, że ludzie mieli różne oczekiwania co do odpowiedzi na pytanie, które oczekiwało odpowiedzi „tak”. Zobacz odmiany w poniższym przykładzie kodu.

Z pewnością musi być lepszy sposób niż to, co wymyśliłem? Jaka jest na to twoja czytelna i krótsza forma ?

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
Zagłosowano za zamknięcie. Chociaż jestem zainteresowany tym pytaniem, prawdopodobnie jest to raczej pytanie programistyczne, więc powinno być na SO.
phunehehe

Odpowiedź programowa może być podobna do Bash: Sprawdź, czy istnieje element tablicy
sprawdź

3
@phunehehe: Nie zgadzam się z przejściem na SO, nie tylko dlatego, że mamy historię akceptowania programowania powłoki, ale także dlatego, że nie chodzi tylko o to, jak to zrobić, ale także o to, jaka powinna być specyfikacja.
Gilles „SO- przestań być zły”

4
Napisałem kiedyś taki skrypt. Następnie program został przetłumaczony na język francuski i chiński uproszczony. Przejrzałem francuską wersję i zobaczyłem, że mój monit został przetłumaczony na „Enter oui or non”, ale oczywiście kod nadal chciał „Y *” lub „N *”
Ben Jackson

Odpowiedzi:


15

Użycie a casejest w pewnym stopniu równoważne, ale nie doskonałe, ponieważ podobne zdania YEsą akceptowane.

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

3
Powiedziałbym, że zamiary użytkownika są całkiem jasne od „ye”.
Aeyoun

48

Standard UNIX udostępnia przykładowy kod do tego celu za pomocą localenarzędzia :

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

Wartość „yesexpr” w POSIXustawieniach regionalnych (i w angielskich ustawieniach regionalnych w prawdziwych systemach) to "^[yY]". Należy to interpretować jako rozszerzone wyrażenie regularne. Zobacz także noexpr.


1
Miły. Ale wydaje mi się, że jestem idiotą. Gdzie mogę znaleźć listę argumentów, które localeo tym wiedzą? Strona podręcznika w moim systemie Mac OS 10.5 chyba ich nie ma.
dmckee

Miły. Czy możesz podać link do źródła?
Aeyoun

3
@dmckee możesz zrobić locale -k LC_MESSAGES(i dla innych LC_cokolwiek), lub zobacz tutaj dla tych zdefiniowanych przez standard. @Daniel do jakiego źródła oprócz strony narzędzia ustawień regionalnych, do której prowadzi link?
Random832

1
Świetna odpowiedź, zdecydowanie powinna być zaakceptowana.
jlliagre

6

Pozostanie w bash (lub dowolnej innej powłoce, jeśli wyświetlisz monit niezależnie):

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

Ten akceptuje odpowiedzi jak ynrównie Tak  y(z pierwotnego miejsca) Ponieważ nie, a wlkjzuhfodjak nie, co może nie być optymalna, ale jest zgodna z typowych podpowiedzi muszli: to jak rm -i, find -oki robią to inni.

Pozwala to uniknąć całego problemu internacjonalizacji: w innych językach trzeba byłoby przetłumaczyć oczekiwane odpowiedzi. Nie ma wtedy standardowej metody powłoki; możesz przejść do okna dialogowego , ale wtedy twój skrypt będzie wymagał jego instalacji (jest dostępny w wielu dystrybucjach, ale nie zawsze jest instalowany domyślnie).

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

3

Zwykle używam prostej funkcji:

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

Funkcja zwraca tylko 0, Yczy ywprowadzono lub , czy wprowadzono 1cokolwiek innego. Może być używany z if...fi:

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

Lub po prostu tak:

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

Zdejmij, -saby mieć wizualną historię tego, co zostało wpisane.
Tom Hale,

0

Właśnie zmodyfikowałem @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.....
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.