Кращий спосіб прийняття варіантів "Так" із запиту оболонки


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

2
Голосували за закриття. Хоча я цікавлюсь питанням, це, мабуть, більше питання програмування, так що це повинно бути на ПО.
phunehehe

Відповідь програмування може бути чимось на зразок Bash: Перевірте, чи існує елемент масиву
phunehehe

3
@phunehehe: Я не погоджуюся з переходом на SO, не тільки тому, що ми маємо історію прийняття програмування оболонок, а й тому, що це не лише питання про те, як це зробити, а й питання про те, якою повинна бути специфікація.
Жиль "ТАК - перестань бути злим"

4
Я колись писав такий сценарій. Потім програма була перекладена на французьку та спрощену китайську. Я знехтував французьку версію і побачив, що моя підказка була переведена на "Enter oui or 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

3
Я б сказав, що намір користувача досить зрозумілий з "так".
Ейюн

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.


1
Приємно. Але я, здається, ідіот. Де я можу знайти список аргументів, localeпро які відомо? Сторінка man у моєму вікні Mac OS 10.5, схоже, їх не має.
dmckee

Приємно. Не могли б ви зв’язатись із джерелом?
Ейюн

3
@dmckee ви можете зробити locale -k LC_MESSAGES(і для інших LC_залежно) або подивитися тут ті, які визначені стандартом. @Daniel Яке джерело, окрім сторінки утиліти локалі, на яку я посилався?
Випадково832

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.....
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.