Лучший способ принять варианты «Да» из командной строки

27

Юзабилити-тестирование сценария оболочки, которое я написал, показало, что у людей разные ожидания относительно того, как ответить на вопрос, который ожидал «да» в качестве ответа. См. Варианты в приведенном ниже примере кода.

Конечно, должен быть лучший способ, что я придумал? Какова ваша читаемая и более короткая форма ?

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
Aeyoun
источник
2
Проголосовал за закрытие. Хотя я заинтересован в этом вопросе, это, вероятно, больше вопрос программирования, так что должно быть на SO.
phunehehe
Программный ответ может быть что-то вроде Bash: Проверьте, существует ли элемент массива
phunehehe
3
@phunehehe: я не согласен с переходом на SO не только потому, что у нас есть история принятия программирования на оболочку, но и потому, что это не только вопрос о том, как это сделать, но и вопрос о том, какой должна быть спецификация.
Жиль "ТАК - перестань быть злым"
4
Однажды я написал такой же сценарий. Затем программа была переведена на французский и упрощенный китайский. Я просмотрел французскую версию и увидел, что мое приглашение было переведено как «Введите oui или non», но, конечно, код все еще хотел «Y *» или «N *»
Бен Джексон,

Ответы:

15

Использование a caseв некоторой степени эквивалентно, но не идеально, так как утверждения типа YEпринимаются.

read -p 'Answer this question with yes: ' answer
case "${answer}" in
    [yY]|[yY][eE][sS])
        echo 'Surely this can be written better?' ;;
esac
sakisk
источник
3
Я бы сказал, что намерение пользователя довольно ясно из «вы».
Aeyoun
48

Стандарт UNIX предоставляет пример кода для этого с помощью localeутилиты :

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

Значение для 'yesexpr' в POSIXлокали (и в английских локалях в реальных системах) равно "^[yY]". Это должно быть интерпретировано как расширенное регулярное выражение. Смотрите также noexpr.

Random832
источник
1
Ницца. Но я, кажется, идиот. Где я могу найти список аргументов, localeо которых известно? Страница man на моем Mac OS 10.5, похоже, не содержит их.
dmckee
Ницца. Не могли бы вы дать ссылку на источник?
Aeyoun
3
@dmckee вы можете сделать locale -k LC_MESSAGES(и для других LC_ что угодно), или посмотреть здесь для тех, которые определены стандартом. @Daniel, какой источник, кроме служебной страницы локали, на которую я сделал ссылку?
Random832
1
Отличный ответ, обязательно должен быть принятым.
Jlliagre
6

Оставаться в bash (или любой другой оболочке, если вы отображаете приглашение независимо):

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

Это принимает ответы , как , ynкак да,  y(с начальным пространством) , как нет, и wlkjzuhfodкак ни один , который не может быть оптимальным , но согласуется с типичными подсказками оболочки: вот как rm -i, find -okи это делают другие.

Это полностью исключает проблему интернационализации: на других языках вам нужно будет перевести ожидаемые ответы. Там нет стандартного метода оболочки тогда; Вы можете перейти к диалогу , но тогда ваш скрипт потребует его установки (он доступен во многих дистрибутивах, но не всегда устанавливается по умолчанию).

if dialog --yesno "Choose yes" 0 0; then 
Жиль "ТАК - перестань быть злым"
источник
3

Я обычно использую простую функцию:

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

Функция просто возвращает, 0если Yили yвведено, и 1если что-либо еще введено. Может использоваться с if...fi:

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

Или просто так:

Confirm "Type y" && echo "You typed y"
Чак Меткалф
источник
Снимите, -sчтобы иметь визуальную историю того, что было напечатано.
Том Хейл,
0

Только что обновил @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

Тест

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.....
Рахул Патил
источник