Tạo menu đơn giản trong Bash shell bằng SELECT LOOP

Cấu trúc select loop trong bash không phải là một phần của tiêu chuẩn posix. Mặc dù vậy, nó được sử dụng rộng rãi để dễ dàng tạo các menu tương tác trong tập lệnh shell. Bài đăng này trình bày cách sử dụng vòng lặp chọn với từ khóa select trong bash để tạo một menu có thể chọn đơn giản trong tập lệnh shell.
bash-shell

SELECT LOOP trong tập lệnh shell là gì?

https://www.shell-tips.com/bash/select-loop/#gsc.tab=0

Cấu trúc SELECT là một cách viết tắt bash để tạo một menu được đánh số. Nó không phải là một phần của tiêu chuẩn shell POSIX. Đây là một lệnh hữu ích để dễ dàng yêu cầu người dùng chọn từ danh sách các tùy chọn.

Bất chấp tên của nó, SELECT LOOP không phải là một phần của cấu trúc biến thể của bash loop. Giống như từ khóa if trong bash, từ khóa SELECTlà một phần của cấu trúc có điều kiện trong bash shell.

Cú pháp SELECT LOOP rất gần với cú pháp của vòng lặp for: 

select name [in words …]; do commands; done

Danh sách các từ sau từ khóa in được bash shell mở rộng để tạo danh sách các mục (menu). Các menu được in trên luồng đầu ra lỗi tiêu chuẩn (STDERR), đứng trước một số. Tương tự như việc dùng loop trong bash shell, nếu [in words …] bị bỏ qua, các tham số vị trí sẽ được sử dụng như thể sử dụng trong "$@".

Vòng lặp chọn sử dụng biến PS3 để nhắc người dùng. Lựa chọn của người dùng được đọc từ đầu vào tiêu chuẩn. Nếu lựa chọn của người dùng trống, menu và lời nhắc PS3 sẽ hiển thị lại. Nếu một số được cung cấp bởi người dùng, thì biến tên từ vòng chọn sẽ được đặt thành từ tương ứng (mục menu). Bất kỳ giá trị nào khác được đọc đều khiến tên được đặt thành null.

Lệnh SELECT hoàn tất khi EOF được đọc hoặc lệnh break. Dòng read (number) được lưu vào biến REPLY.

Dưới đây là một ví dụ để nhắc người dùng chọn tên tệp từ thư mục hiện tại và hiển thị tên tệp cũng như chỉ mục của tệp đã chọn.
tạo 1 file có tên là select.sh và đưa nội dung ví dụ vào
 
select filename in *;
do
    echo "You selected $filename ($REPLY)"
    break;
done

Gán quyền thực thi cho file select.sh
chmod +x select.sh

thực thi file select.sh
root@test-scripts:~/test# ./select.sh

Kết quả như dưới

Vòng lặp SELECT có thể được lồng vào nhau để tạo các menu con, mặc dù biến nhắc nhở của PS3 không bị thay đổi khi vào vòng lặp lồng nhau. Trong trường hợp như vậy, hãy đảm bảo đặt biến PS3 tương ứng.

Làm cách nào để tạo menu chọn trong bash?

Dưới đây là một ví dụ sử dụng SELECT LOOP để tạo menu có thể chọn từ biến thể bash array, sử dụng biến PS3 để đặt lời nhắc người dùng và hiển thị menu và chỉ mục đã chọn.

Ví dụ: Đoạn script yêu cầu người dùng lựa chọn một con vật từ danh sách trong option, từ khóa select để tạo một menu từ danh sách của option. Sau đó, người dùng có thể chọn một tùy chọn từ menu bằng cách nhập số tương ứng. Đầu tiên, mã sẽ kiểm tra xem người dùng đã chọn một con vật chưa. Nếu người dùng đã chọn "chair" hoặc "apple",  sẽ in thông báo cho biết $menu is not an animal. Ngược lại, mã sẽ in thông báo cho biết $menu is an animal
 
PS3="Choose an animal: "
options=(cat dog mouse chair cow bird apple)
select menu in "${options[@]}";
do
  echo -e "\nyou picked $menu ($REPLY)"
  if [[ $menu == "chair" || $menu == "apple" ]]; then
    echo -e "$menu is not an animal\n"
  else
    echo "$menu is an animal"
    break;
  fi
done
  • Biến PS3 được sử dụng để đặt lời nhắc sẽ được hiển thị cho người dùng. Trong trường hợp này, lời nhắc là "Choose an animal:".
  • Mảng options được sử dụng để lưu trữ danh sách các tùy chọn mà người dùng có thể chọn. Trong trường hợp này, mảng chứa các mục sau: "cat", "dog", "mouse", "chair", "cow", "bird", và "apple".
  • Từ khóa select được sử dụng để tạo menu từ danh sách các tùy chọn. Biến menu được sử dụng để lưu trữ tùy chọn mà người dùng chọn.
  • Từ khóa do được sử dụng để bắt đầu một vòng lặp. Vòng lặp sẽ tiếp tục chạy cho đến khi người dùng chọn một tùy chọn từ menu.
  • Lệnh echo được sử dụng để in một thông báo.
  • Câu lệnh if được sử dụng để kiểm tra xem người dùng đã chọn một con vật hay chưa. Nếu người dùng chọn "chair" hoặc "apple", mã sẽ in thông báo cho biết $menu is not an animal. Nếu không, mã sẽ in thông báo cho biết $menu is an animal.
  • Câu lệnh break dùng để thoát khỏi vòng lặp.
Khi chạy ví dụ này, kết quả đầu ra sẽ như bên dưới khi lần đầu tiên chọn tùy chọn 4 rồi chọn 1.

Sử dụng PIPE để làm đầu vào cho SELECT LOOP

Như đã đề cập trước đó, lệnh SELECT hoàn thành khi đọc EOF và nó đọc lựa chọn của người dùng từ STDIN (đầu vào tiêu chuẩn là đầu vào bàn phím trong script)
Mặc dù đây không phải là trường hợp khi lệnh được đưa vào tập lệnh của bạn từ bàn phím, nhưng đầu ra tiêu chuẩn STDOUT của lệnh được trước đó sẽ trở thành STDIN.