select
select name [in words …]; do commands; done
如果in words存在,就会把words打印到标准错误(standard error)流里,并显示PS3提示符,等待从标准输入中读取读取一行。
如果in words不存在,等同于in “$@”,即将位置参数打印到标准错误(standard error)流里,并显示PS3提示符,等待从标准输入中读取读取一行。
$ select var in a b c d; do echo $var;break; done
1) a
2) b
3) c
4) d
#? 1
a
$ bash -c "select var; do echo $var;break; done" -s a b c d
1) a
2) b
3) c
4) d
#? 1
a
- 如果从标准输入里读取的是空行,选项列表和PS3会继续显示
$ select var in a b c d; do echo $var;break; done
1) a
2) b
3) c
4) d
#?
1) a
2) b
3) c
4) d
#?
-
如果从标准输入里读取的是EOF字符(通常由组合键Ctrl+d输入),select退出
-
如果从标准输入里读取的是对应选项的数字,name的值就会被设置为数字对应的word.
-
如果从标准输入里读取的不是空行,也不是EOF字符,但不对应任何选项的数字,name的值为null
从标准输入里读取的行,都会保存在变量REPLY里。
$ select var in a b c d; do echo $var;break; done
1) a
2) b
3) c
4) d
#? sdf
$ echo $REPLY
sdf
以上四种输入,第3和第4种输入会使commands被执行。如果没有遇到break命令被执行,words列表和PS3会在命令执行完后再次显示,再次从标准输入中读取一行,进行下一次的执行。break命令能退出select. 个人不建议在select的commands里处理复杂的事务,原因是select的退出方式只有两种:从标准输入中读到了EOF (Ctrl + d)和break命令。而不由commands的退出状态决定。
可以参考以下方式来"强迫"输入正确的选项才能退出select,然后再根据var变量的值进行后面的处理。
$ select var in a b c d; do [ -n "$var" ] && echo you select $var &&break; done
或者更友好的方式
$ select var in a b c d; do ([ -n "$var" ] || ! echo please select right option ) && echo you select $var && break; done