Cách tốt hơn để chấp nhận các biến thể của 'Có' từ dấu nhắc trình bao


27

Kiểm tra khả năng sử dụng của một tập lệnh shell tôi đã viết rằng mọi người có những kỳ vọng khác nhau về cách trả lời một câu hỏi mong đợi "có" như câu trả lời. Xem các biến thể trong ví dụ mã dưới đây.

Chắc chắn phải có một cách tốt hơn mà những gì tôi nghĩ ra? Hình thức dễ đọcngắn hơn của bạn là gì về điều này?

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
Bình chọn để đóng. Trong khi tôi quan tâm đến câu hỏi, có lẽ đó là câu hỏi về lập trình nhiều hơn, vì vậy nên có trên SO.
phunehehe

Câu trả lời lập trình có thể giống như Bash: Kiểm tra xem phần tử mảng có tồn tại hay không
phunehehe

3
@phunehehe: Tôi không đồng ý với việc chuyển sang SO, không chỉ bởi vì chúng tôi có lịch sử chấp nhận lập trình shell, mà còn bởi vì đó không chỉ là câu hỏi về cách thực hiện mà còn là câu hỏi về thông số kỹ thuật nên là gì.
Gilles 'SO- ngừng trở nên xấu xa'

4
Tôi đã viết một kịch bản giống như vậy một lần. Sau đó, chương trình được dịch sang tiếng Pháp và tiếng Trung giản thể. Tôi đọc lướt phiên bản tiếng Pháp và thấy lời nhắc của mình được dịch thành "Nhập oui hoặc không" nhưng tất nhiên mã vẫn muốn "Y *" hoặc "N *"
Ben Jackson

Câu trả lời:


15

Sử dụng một casephần nào đó tương đương nhưng không hoàn hảo vì các câu lệnh như YEđược chấp nhận.

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

3
Tôi muốn nói rằng ý định của người dùng khá rõ ràng từ 'các ngươi'.
Aeyoun

48

Tiêu chuẩn UNIX cung cấp mã ví dụ cho việc này bằng cách sử dụng localetiện ích :

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

Giá trị cho 'yesexpr' trong POSIXmiền địa phương (và trên các ngôn ngữ tiếng Anh trên các hệ thống thực) là "^[yY]". Nó được hiểu là một biểu thức chính quy mở rộng. Xem thêm noexpr.


1
Tốt đẹp. Nhưng tôi dường như là một thằng ngốc. Tôi có thể tìm danh sách các đối số localebiết về đâu? Trang nam trên hộp Mac OS 10.5 của tôi dường như không có chúng.
dmckee

Tốt đẹp. Bạn có thể vui lòng liên kết trở lại nguồn?
Aeyoun

3
@dmckee bạn có thể làm locale -k LC_MESSAGES(và cho LC_whatever khác), hoặc xem ở đây cho những người được xác định theo tiêu chuẩn. @Daniel nguồn nào khác ngoài trang tiện ích bản địa mà tôi đã liên kết?
Random832

1
Câu trả lời tuyệt vời, chắc chắn nên được chấp nhận.
jlliagre

6

Ở trong bash (hoặc bất kỳ shell nào khác nếu bạn hiển thị lời nhắc một cách độc lập):

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

Này chấp nhận phản ứng như ynlà có,  y(với một không gian ban đầu) như là không có, và wlkjzuhfodnhư là không có, mà có thể không được tối ưu nhưng là phù hợp với nhắc nhở vỏ điển hình: đó là cách rm -i, find -okvà những người khác làm điều đó.

Điều này tránh toàn bộ vấn đề quốc tế hóa: trong các ngôn ngữ khác, bạn sẽ cần dịch các câu trả lời dự kiến. Không có phương pháp vỏ tiêu chuẩn nào sau đó; bạn có thể chuyển sang hộp thoại , nhưng sau đó tập lệnh của bạn sẽ yêu cầu cài đặt nó (nó có sẵn trong nhiều bản phân phối nhưng không phải lúc nào cũng được cài đặt theo mặc định).

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

3

Tôi thường sử dụng một chức năng đơn giản:

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

Hàm chỉ trả về 0nếu Yhoặc yđược nhập và 1nếu có bất cứ thứ gì khác được nhập. Nó có thể được sử dụng với if...fi:

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

Hoặc chỉ như thế này:

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

Cởi bỏ -sđể có một lịch sử trực quan về những gì đã gõ.
Tom Hale

0

Chỉ cần sửa đổi lại @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

Kiểm tra

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.....
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.