Sử dụng lệnh `select` để in một menu trong Bash


10

Tôi đang cố gắng thực hiện một menu đơn giản bằng cách sử dụng selectlệnh. Kịch bản (cho mục đích thử nghiệm) như sau:

#!/bin/bash
echo "*******************"
PS3='Select an option and press Enter: '
options=("apache" "named" "sendmail")
select opt in "${options[@]}"
do
  case $opt in
        "apache")
          date
          ;;
        "named")
          echo "test"
          ;;
        "sendmail")
          echo "test 2"
          ;;
        *) echo "invalid option";;
  esac
done
echo "*********************"

Kịch bản không nhận ra bất kỳ đầu vào hợp lệ nào tôi đưa ra và luôn in thông báo "tùy chọn không hợp lệ". Điều gì đang làm sai trong kịch bản này?


4
Đầu vào của bạn là 1, 2 hoặc 3, phải không?
enzotib

Câu trả lời:


11

Menu của bạn được hiển thị bởi select sẽ trông như sau:

1) apache
2) named
3) sendmail
Select an option and press Enter: 

Tại thời điểm này, bạn nhập "1" hoặc "2" hoặc "3": bạn không nhập từ.

Ngoài ra, selectsẽ lặp cho đến khi thấy breaklệnh, vì vậy bạn muốn điều này:

  case $opt in
        "apache")
          date
          break
          ;;
        "named")
          echo "test"
          break
          ;;
        "sendmail")
          echo "test 2"
          break
          ;;
        *) echo "invalid option";;
  esac

Nếu bạn muốn cho phép người dùng nhập số hoặc từ, bạn có thể viết điều này:

select opt in "${options[@]}"; do
  case "$opt,$REPLY" in
    apache,*|*,apache)     do_something; break ;;
    named,*|*,named)       do_something; break ;;
    sendmail,*|*,sendmail) do_something; break ;;
  esac
done

Dấu phẩy không có ý nghĩa cú pháp, chỉ cần có thể khớp mẫu trên biến $ REPLY (là giá trị mà người dùng thực sự đã nhập) hoặc biến $ opt


Các selectlệnh cần có một break, không case.
glenn jackman

Cảm ơn! Tôi đã không nhận ra rằng đó là tùy chọn số. Duhh!
Sumod

Hah, tôi cũng lập trình trong C và, bạn cần breakcó một phần trong mỗi phần. Tuy nhiên, bạn sẽ không bao giờ cần breakmột trường hợp ... khối esac trong tập lệnh shell . Nó có thể xảy ra rất dễ dàng để làm cho chúng trộn lẫn. :-)
cú pháp

1
@syntaxerror, bạn nói đúng, bạn không cần phải breakcho case. Tuy nhiên, bạn cần một breakđể thoát khỏi selectvòng lặp.
glenn jackman

@glenn jackman Tôi muốn biến điều này thành một bình luận hữu ích hơn (xem tiếp). Vì vậy, sẽ thật tuyệt nếu bạn đồng ý xóa bình luận của mình từ 12:55. Tôi sẽ làm tương tự với tôi, tất nhiên.
cú pháp

3

$optBiến của bạn sẽ được đặt thành từ tùy chọn tương ứng với số mà người dùng nhập vào. Nếu bạn muốn xem những gì người dùng thực sự gõ, hãy nhìn vào $REPLY.


1
Cho rằng caseso sánh $optvới "apache", "được đặt tên" và "sendmail", điều đó là chính xác và không có gì phải thay đổi.
manatwork

@manatwork, trừ khi OP muốn người dùng gõ các từ "apache", "có tên" hoặc "sendmail" thay vì nhấn 1, 2 hoặc 3.
Kusalananda

Hấp dẫn. $ REPLY giữ 1/ 2/ 3và $ opt giữ apache/ named/sendmail
Peter.O

@fred, vâng, $REPLYlà bất cứ điều gì người dùng gõ và nếu đó là một số hợp lệ thì đó $optsẽ là từ tương ứng với số đó.
Kusalananda
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.