Cara yang lebih baik dalam menerima variasi 'Ya' dari prompt shell

27

Pengujian kegunaan dari skrip shell yang saya tulis menemukan bahwa orang-orang memiliki harapan yang berbeda tentang cara menjawab pertanyaan yang mengharapkan 'ya' sebagai jawabannya. Lihat variasi dalam contoh kode di bawah ini.

Tentunya harus ada cara yang lebih baik dari apa yang saya temukan? Apa bentuk Anda yang dapat dibaca dan lebih pendek dari ini?

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
sumber
2
Memilih untuk menutup. Sementara saya tertarik pada pertanyaan, itu mungkin lebih merupakan pertanyaan pemrograman, jadi harus di SO.
phunehehe
Jawaban pemrograman mungkin kira-kira seperti Bash: Periksa apakah elemen array ada
phunehehe
3
@ phunehehe: Saya tidak setuju dengan pindah ke SO, tidak hanya karena kami memiliki sejarah menerima pemrograman shell, tetapi juga karena itu bukan hanya pertanyaan tentang bagaimana melakukannya tetapi juga pertanyaan tentang apa spesifikasi yang seharusnya.
Gilles 'SANGAT berhenti menjadi jahat'
4
Saya menulis naskah seperti itu sekali. Kemudian program itu diterjemahkan ke bahasa Prancis dan Cina Sederhana. Saya membaca sekilas versi Perancis dan melihat prompt saya diterjemahkan ke "Enter oui or non" tetapi tentu saja kode itu masih menginginkan "Y *" atau "N *"
Ben Jackson

Jawaban:

15

Menggunakan a caseagak setara tetapi tidak sempurna karena pernyataan suka YEditerima.

read -p 'Answer this question with yes: ' answer
case "${answer}" in
    [yY]|[yY][eE][sS])
        echo 'Surely this can be written better?' ;;
esac
sakisk
sumber
3
Saya akan mengatakan niat pengguna cukup jelas dari 'kamu'.
Aeyoun
48

Standar UNIX menyediakan contoh kode untuk ini menggunakan localeutilitas :

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

Nilai untuk 'yesexpr' di POSIXlokal (dan pada bahasa Inggris di sistem nyata) adalah "^[yY]". Itu harus ditafsirkan sebagai ekspresi reguler yang diperluas. Lihat juga noexpr.

Random832
sumber
1
Bagus. Tapi saya sepertinya idiot. Di mana saya dapat menemukan daftar argumen yang localemengetahui tentang? Halaman manual pada kotak Mac OS 10.5 saya sepertinya tidak memilikinya.
dmckee
Bagus. Bisakah Anda menautkan kembali ke sumbernya?
Aeyoun
3
@ dmckee dapat Anda lakukan locale -k LC_MESSAGES(dan untuk LC_ lainnya apa pun), atau lihat di sini untuk yang didefinisikan oleh standar. @Aniel apa sumber selain halaman utilitas lokal yang saya tautkan?
Random832
1
Jawaban yang bagus, pasti yang diterima.
jlliagre
6

Tetap di bash (atau shell lain jika Anda menampilkan prompt secara mandiri):

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

Ini menerima respons seperti ynya,  y(dengan spasi awal) sebagai tidak, dan wlkjzuhfodtidak, yang mungkin tidak optimal tetapi konsisten dengan prompt shell yang khas: begitulah rm -i, find -okdan yang lain melakukannya.

Ini menghindari seluruh masalah internasionalisasi: dalam bahasa lain, Anda perlu menerjemahkan tanggapan yang diharapkan. Tidak ada metode shell standar; Anda dapat beralih ke dialog , tetapi kemudian skrip Anda akan memerlukannya untuk diinstal (itu tersedia di banyak distribusi tetapi tidak selalu diinstal secara default).

if dialog --yesno "Choose yes" 0 0; then 
Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Saya biasanya menggunakan fungsi sederhana:

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

Fungsi hanya mengembalikan 0jika Yatau ydimasukkan dan 1jika ada hal lain yang dimasukkan. Ini dapat digunakan dengan if...fi:

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

Atau seperti ini:

Confirm "Type y" && echo "You typed y"
Chuck Metcalfe
sumber
Lepaskan -suntuk memiliki riwayat visual dari apa yang diketik.
Tom Hale
0

Baru saja memodifikasi @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

Uji

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.....
Rahul Patil
sumber