shell程序设计(七)选项和参数

Bash ginotang 884℃ 0评论

选项和参数

有时候,我们会把它们混淆,但严格来说,选项(option)和参数(parameter)并不等同。选项用于设置程序的行为,而参数多数都是程序将要被处理的数据。

在shell编程中,这两个东西是必不可少的,因此,如何处理好它们是关键。

先看一个例子:

上面的命令中,-p和-i是选项,它们都有各自的选项值,分别是1000和identify,而root@192.168.0.10则是参数,告诉ssh命令使用root用户登录到远程主机。

在脚本中使用选项和参数

在shell脚本中,无论是选项还是参数,都是通过位置参数的形式存在的。例如:

在shell中运行:

通常,选项都是以-开头,后面跟着的就是选项值,下面是是参数遍历的例子:

方法是通过while循环检查位置参数$1的值是否为空,如果不为空则继续遍历,shift的作用是把已经处理的位置参数移除,直到参数栈为空。

然而这种方法存在一个问题,就是不能很好区分选项和参数,参数不多的时候问题不是很明显,但是一旦参数多了,问题处理起来就变得麻烦

区分选项和参数

set方法有一个选项--(双横线),该选项的作用是把--后面的所有参数都变为位置参数,我们也可以利用这个原理区分选项和参数:

运行结果:

处理带选项值的选项

像一开头的ssh例子,有两个选项是有值的,因此要处理这些带值的选项。

运行:

注意处理-b选项的时候,因为跟在-b后面的就是选项的值,当前-b的位置是$1,即它的选项值就是$2,所以把这个值保存在变量param中,因为$2已经处理,因此要把它shift掉。

使用getopt优化程序

虽然使用--可以区分选项和参数,但是我们在使用系统的程序的时候,很少这样传递参数的,--的出现显得非常奇怪;而且,另一个问题是,上面的脚本不能很好地处理选项的合并写法,例如-ab这样的形式。幸运的是,系统提供了getopt程序。

getopt语法:

getopt在处理选项上面有些不一样,它通过冒号(:)指定哪些选项允许带值。例如:

b后面有一个冒号,说明它是可以带值的选项,而a没有冒号,即我们不能为它传递选项值。getopt返回的是格式化好的字符串,它已经把选项和参数区分开,而且把有值和没有值的选项也已经排列好。

实际上,getopt返回的字符串还不能直接使用,它需要通过set来设置位置参数。

通过$()捕获getopt的输出,然后使用set --把这些输出设置为位置参数。后面的照常处理即可。通过getopt的好处是我们在传递参数的时候不需要再使用--,而且可以使用合并选项的写法。

虽然getopt程序解决了一些问题,但是它本身对于双引号并不是十分友好,例如:

我们的本意是,“test param”是完整的一个选项值,但是getopt却不能识别,硬生生地把它们拆散了。

使用getopts

getopts是getopt的增强版,上面的问题getopts都可以解决。在使用方法上面,getopts和getopt也有不同,getopt是一次处理所有的参数,然后返回一个格式化好的字符串,而getopts是每次处理一个遇到的参数,直到没有参数位置。

注意a前面有一个冒号,这个冒号的作用是抑制错误输出,即当遇到不匹配的选项的时候不提示错误。

在循环中,getopts每次把检测到的选项保存到opt参数中,以便在后面的语句中使用,不匹配的选项在opt中保存为?(问号)。getopts中有两个特殊的预定义变量,一个是OPTARG,另一个是OPTIND(option index)。OPTARG是解析到的选项值,OPTIND是选项的索引,表示下一个要处理的选项索引值。

另外,getopts在处理选项的时候会自动把-(横杠)去掉,因此,我们在编写脚本的时候不需要添加这个横杠。

运行结果:

使用getopts处理选项和参数

getopts中不使用--区分选项和参数,而是配合OPTIND变量来处理的。

实际上,OPTIND的长度是optstring(这里是ab:cd)的长度加1,因为OPTIND是下一个要处理的选项索引,因此,当处理完所有的选项后,OPTIND的值就是第一个要处理的参数的位置。所以,上面shift的时候要减去一。

运行结果:

可见,getopts可以正确处理双引号中有空格的字符串。

转载请注明:Pure nonsense » shell程序设计(七)选项和参数

喜欢 (0)
0 0 投票数
文章评分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x
()
x