本文介绍了bash的select复合命令,可以提供一个菜单列表供用户选择。select命令格式select命令示例自定义提示信息修改菜单项分隔符select命令格式在Linux的Bashshell中,可以使用select复合命令(compoundcommand)提供一个菜单列表供用户选择,并根据以用户的选择处理它。查看manbash里面对select命令的说明如下:selectname[inword];做清单;done展开“in”之后的单词列表,生成一个项目列表。扩展单词集打印在标准错误上,每个单词前面都有一个数字。如果省略“inword”,则打印位置参数。然后显示PS3提示,并从标准输入中读取一行。如果该行包含与显示的单词之一相对应的数字,则name的值将设置为该单词。如果该行为空,则再次显示单词和提示。如果读取到EOF,则命令完成。读取的任何其他值都会导致名称设置为空。读取的行保存在可行的REPLY中。列表在每次选择后执行,直到执行中断命令。select的退出状态是list中执行的list命令的退出状态,如果没有执行命令则为零。在select指令格式中,[inword]表示"inword"是可选参数,用于提供菜单列表,实际输入的时候不需要输入输入[]两个字符,name变量会保存用户选中的菜单项的内容。可以获取name变量的值来查看用户的选择。每次用户输入选择时,都会执行列表指定的命令。注意:这里的[]不是bash中的条件判断命令。bash有一个【条件判断命令,其格式为[parameters...],两者格式类似,注意区分,不要混淆。当不提供inword参数时,select命令默认使用in"$@"参数,即传入脚本或传入函数的参数列表作为菜单选项。select命令使用inword参数来指定菜单列表。不同的菜单项以空格分隔。不要把整个菜单列表用双引号括起来,否则会被当做一个菜单项。当用双引号括起菜单列表时,整个菜单列表被视为一个选项。如果一个选项的内容确实包含空格,您可以将选项的内容单独用双引号括起来,以防止选项被拆分成多个选项。选择后,select命令不会自动退出,而是等待用户继续选择。需要执行break命令退出,也可以按CTRL-D输入EOF退出。进入EOF退出后,name变量值将与之前的值保持不变,不会自动清零。在select命令的内部语句中,可以使用exit命令直接退出整个脚本的执行,从而退出select的选择。如果select命令是在函数内部调用的,可以使用return命令直接退出整个函数,从而退出select选择。选择命令示例假设有一个testselect.sh脚本,内容如下:#!/bin/bashselectanimalinliontigerpandaflower;如果["$animal"="flower"]做;然后回声“花不是动物。”breakelseecho"Chooseanimalis:$animal"fidoneecho"++++Enternewselect++++"在"liontigerpanda"中选择动物;doecho"Yourchooseis:$animal"breakdone这个脚本的第一个select命令定义了四个菜单项:lion、tiger、panda和flower。如果用户选择了flower,则执行break命令退出select选择;否则,将打印用户选择的动物名称。第二个选择命令用双引号将菜单选项括起来,以便您可以看到添加双引号的效果。执行脚本,输出如下:$./testselect.sh1)lion2)tiger3)panda4)flower#?1选择动物是:狮子#?2选择动物是:tiger#?7选择动物是:#?lionChooseanimalis:#?4Flowerisnotanimal.++++Enternewselect++++1)liontigerpanda#?1你选择的是:liontigerpanda可以看到,select命令需要通过菜单项前面的数字选择对应的item,并将对应item的名称赋值给指定的animal变量。为菜单项本身输入字符串不会选择菜单项。输入无效的菜单项编号不会引发错误。这两种情况都会清除animal变量的值。这#?自定义提示信息上面是bashPS3提示符,我们可以给PS3变量赋值,然后执行select命令打印自定义提示信息。例如:$PS3="Enjoyyourchoice:>"$selectanimalinliontiger;回声“选择:$动物”;休息;done1)lion2)tigerEnjoyyourchoose:>1Choose:lion可见,是一个PS3变量赋值后,select命令会打印赋值的内容作为提示。修改菜单项的分隔符我们可以修改bash的IFS变量值来指定不同菜单项之间的分隔符,但是在使用上有一个注意事项,具体说明如下:$IFS=/$animal_list="biglion/smalltiger"$在$animal_list中选择动物;回声“选择:$动物”;休息;done1)biglion2)smalltiger#?1Choose:biglion$在biglion/smalltiger中选择动物;回声“选择:$动物”;休息;done1)big2)lion/small3)tiger#?2Choose:lion/small上例中,将IFS赋值给/,然后定义变量animal_list,用/分隔biglion和smalltiger两项,使用select命令从animal_list变量中获取菜单选项时,您可以看到选项不再以空格分隔,而是在IFS赋值后以/分隔。但是,当select命令不是从animal_list变量中获取菜单选项,而是直接写成biglion/smalltiger命令中的selectanimal时,IFS赋值后依然使用空格分隔选项,而不是/。原因是在bash扩容后使用了IFS进行分词,而使用$animal_list获取animal_list变量的值是扩容,所以出现分词,使用IFS的值分词为几个词。直接写成biglion/smalltiger不展开,所以不用IFS分词。查看manbash对IFS的描述如下:IFSTheInternalFieldSeparator用于扩展后的分词,并使用内置命令read将行分词。默认值是``
