在执行shell脚本时,可以像运行应用程序一样传入相应的参数,在脚本内部根据传入的参数内容执行和它对应的操作。shell脚本中可以通过"$1……$N"形式的符号来引用传入的参数,1~N和传入参数位置相对应的,比如$1表示执行脚本时传入的第一个参数,$2表示传入的第二个参数,以此类推此后传入参数的引用。对于一些只需要很简单的命令行参数的脚本,通过使用$N形式轻松的完成解析,但对于比较复杂的命令行形式的参数,就需要脚本的编写者在脚本中加入复杂的代码对命令行进行解析。
为了减少重复性编程和简化命令行参数处理的过程,shell中为脚本编写者提供了一些命令行处理方法,使用这些方法可以轻松的处理各种形式的命令行参数。这里讲的getopt、getopts就是其中的一些,下面我们来详细介绍如何使用getopt、getopts处理命令行参数。
1、getopts、getopt的区别
在介绍如何使用getopts、getopt处理命令行参数之前,先来简单的说下getopt、getopts两者的各种特点和区别
首先来说getopts,getopts是shell中内建的命令,它的使用语法相对getopt简单,但它不支持长命令参数(--option)。它不会重排列所有参数的顺序,选项参数的格式必须是-d val,而不能是中间没有空格的-dval,遇到非-开头的参数,或者选项参数结束标记--就中止了,如果中间遇到非选项的命令行参数,后面的选项参数就都取不到了,出现的目的仅仅是为了代替getopt较快捷方便的执行参数的分析。
相反的是,getopts的缺点正好是getopt所具有的优点。相对于getopts而言,getopt是一个独立的外部工具(Linux的一个命令),它的使用语法比较复杂,支持长命令参数,会重排参数的顺序。在shell中处理命令行参数时,需要配合其他Linux命令一起使用才行。
总的来说getopts和getopt相比,getopts使用起来比较简单,但只支持短参数,getopt使用起来虽比较复杂,但处理的参数类型比较广泛
2、getopts的使用
2.1 命令格式
getopts optstring name [arg]
optstring:表示要识别的命令行选项形式,如果一个字母后面有一个":",表示该命令行选项后面要跟一个参数。如optsting写成"co:f:",表示支持-c、-o、-f选项识别,-o和-f选项后面需要跟一个参数
name:每次调用它前,getopts都会将下一个选项放置在shell变量$name中,如果传入命令行中不存在name选项,则将其重新初始化
arg:表示要解析参数,在shell脚本中使用时,默认解析的是执行shell脚本传入的参数,所以这个部分可省略不写
值得注意的是,当匹配到一个需要参数的选项时,getopts将选项后面跟的参数存放到shell中的OPTARG变量里,OPTIND表示下一个要被处理的命令行参数的索引。
如果找到一个选项,则返回true; 如果遇到选项结尾或发生错误,则false。
2.2 命令使用
使用getopts,编写一个shell,可支持识别命令行参数-b、-o、-h,其中,-b和-o选项后需要跟一个参数
#!/bin/sh
while getopts ":b:o:h" opt_name #① do case $opt_name in b) echo "-b Option is recognized, argument=$OPTARG" ;; o) echo "-o Option is recognized, argument=$OPTARG" ;; h) echo "-h Option is recognized" ;;
:) echo "$OPTARG Option need a argument"
;; esac done
① 当get optstring name [arg]的optstring以":"开头,表示getopts使用"silent" 错误报告模式。这种模式下,当识别到不在optstring中指定的无效选项时,将无效选项字符放在shell变量OPTARG中,当一个带参数的选项没有指定参数时,将":"存放到name中,将该选项存放到OPTARG中
注意这里的使用getopts时将[arg]部分省略,也可以将它带上:getopts "b:o:h" opt_name "$@",$@表示传入的所有命令行参数
运行结果
./myshell.sh -b home -h -o -b Option is recognized, argument=home -h Option is recognized o Option need a argument
3、getopt的使用
3.1 命令格式
getopt是Linux中的一个命令,通常位于/usr/bin目录中,它可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式。getopt的命令使用有一下的三种格式:
getopt optstring parameters getopt [options] [--] optstring parameters getopt [options] -o|--options optstring [options] [--] parameters
getopt的参数分为两部分:用于修改getopt解析模式的选项(即语法中的options和-o|--options optstring)和待解析的参数(即语法中的parameters部分)。第二部分将从第一个非选项参数开始,或者从"--"之后的第一项内容开始。如果在第一部分中没有给定"-o|--options",则第二部分的第一个参数将用作短选项字符串。
如在Linux的Terminal中输入:get c:b -c file -b home
返回匹配结果如下:
-c file -b -- home
输出结果分为两部分,"--"之前的是模式的匹配的结果,"--"之后的是非选项类型的参数
所谓的非选项类型的参数,即是在parameters中,一个不是以"-"开头,也不是它前面的选项所需的参数,那么它就是一个非选项类型的参数(比如上述输入paramters中的home)。
3.2 命令使用
仅凭getopt命令是不能独立完成shell命令行参数的解析,还需要配合其他命令一起运用才行。我们可以使用这样一种方法,将getopt命令返回的匹配结果重新作为shell的位置参数,我们在循环中去左移动这些位置参数,每移动一次判断是当前参数是那种类型选项,并执行对应操作。当遇到"--"时,命令参数解析完毕,退出循环
getopt返回的结果如何作为shell的传入位置参数呢?此时可以使用shell的内置的set函数,set -- arg,arg中的参数作为shell的新的位置参数,可通过$N进行直接引用
shift用于参数的左移,shift n表示向左移出n个参数,此时的$0的值是调用shift n之前的$(n+1)值
#!/bin/sh SHORTOPTS="h,o:" LONGOPTS="help,output:" ARGS=$(getopt --options $SHORTOPTS #① --longoptions $LONGOPTS -- "$@" ) eval set -- "$ARGS" while true; do case $1 in -h|--help) echo "Print Help Information " shift ;; -o|--output) echo "Output result to $2 directory" shift 2 ;; --) shift break ;; esac done
① --options表示短选项,--longoptions表示长选项,这里使用的是上述getopt命令的第三种形式。
如果--options、--longoptions后要指定多个选项参数,不同选项之间可以通过","进行分割指定;如果选项需要跟随一个参数,该选项后面需要加":",如果选项后面需要跟随一个可选参数,该选项后面需要加"::"
执行结果:
./shell.sh -h --help -o YOCTO --output=Public Print Help Information Print Help Information Output result to YOCTO directory Output result to Public directory
4、小结
通过例子分别展示了如何使用getopt和getopts处理shell的命令行参数,这些方法在shell编程中会经常用到。关于getopt命令使用比较多,这里仅做了一些简单的介绍,详细的信息可以参考man page里手册信息。