9.6. 使用 select 内建命令创建菜单

9.6.1. 概述

9.6.1.1. select 的用法

select 结构可以方便地生成菜单。其语法与 for 循环非常相似

selectWORD[inLIST]; do RESPECTIVE-COMMANDS; done

LIST会被展开,生成一个项目列表。展开结果会打印到标准错误输出;每个项目前面都有一个数字。如果 in LIST 不存在,则会打印位置参数,就像指定了 in $@ 一样。LIST只打印一次。

在打印完所有项目后,PS3提示符会被打印,并从标准输入读取一行。如果这行包含一个与其中一个项目对应的数字,则会将WORD设置为该项目的名称。如果该行是空的,项目和PS3提示符会再次显示。如果读取到 EOF (文件结束) 字符,循环会退出。由于大多数用户不知道 EOF 序列使用哪个组合键,因此最好将 break 命令作为其中一个项目,这样更方便用户。读取行的任何其他值都会将WORD设置为空字符串。

读取的行保存在REPLY变量中。

在每次选择后,会执行 RESPECTIVE-COMMANDS,直到读取到代表 break 的数字。这将退出循环。

9.6.1.2. 示例

这是一个非常简单的例子,但正如你所看到的,它不是很用户友好

[carol@octarine testdir] cat private.sh
#!/bin/bash

echo "This script can make any of the files in this directory private."
echo "Enter the number of the file you want to protect:"

select FILENAME in *;
do
     echo "You picked $FILENAME ($REPLY), it is now only accessible to you."
     chmod go-rwx "$FILENAME"
done

[carol@octarine testdir] ./private.sh
This script can make any of the files in this directory private.
Enter the number of the file you want to protect:
1) archive-20030129
2) bash
3) private.sh
#? 1
You picked archive-20030129 (1)
#?

设置PS3提示符并添加退出的可能性会使其更好

#!/bin/bash

echo "This script can make any of the files in this directory private."
echo "Enter the number of the file you want to protect:"

PS3="Your choice: "
QUIT="QUIT THIS PROGRAM - I feel safe now."
touch "$QUIT"

select FILENAME in *;
do
  case $FILENAME in
        "$QUIT")
          echo "Exiting."
          break
          ;;
        *)
          echo "You picked $FILENAME ($REPLY)"
          chmod go-rwx "$FILENAME"
          ;;
  esac
done
rm "$QUIT"

9.6.2. 子菜单

select 结构中的任何语句都可以是另一个 select 循环,从而在菜单中启用(一个或多个)子菜单。

默认情况下,PS3变量在进入嵌套的 select 循环时不会改变。如果想要在子菜单中使用不同的提示符,请确保在适当的时间设置它。