目录
简介
1. 手工处理选项和参数
2. 使用 getopts 处理多命令行选项
3. 使用 getopt 处理多命令行选项
本文介绍了linux shell中使用命令行选项与命令行参数的方法,在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
1,直接处理,依次对$1,$2,...,$n进行解析,分别手工处理;
2,getopts来处理,单个字符选项的情况(如:-n 10 -f file.txt等选项);
3,getopt,可以处理单个字符选项,也可以处理长选项long-option(如:--prefix=/home等)。
总结:小脚本手工处理即可,getopts能处理绝大多数的情况,getopt较复杂、功能也更强大。
当我们编写的 Shell 脚本只接收少量命令行选项时,且已知选项和参数位置格式,使用 case 语句对其进行处理是比较方便的。下面是一个简单的使用示例
#! /bin/bash
# 将第一个命令行参数赋值给变量 opt
opt=$1
# 将第二个命令行参数赋值给变量 filename
filename=$2
# 定义函数 checkfile
checkfile() {
# 如果没有指定文件名,则显示缺少文件名,并退出脚本的运行
if [ -z $filename ]
then
echo "File name missing"
exit 1
elif [ ! -f $filename ]
then
echo "The file $filename doesn't exist!"
exit 2
fi
}
case $opt in
-e|-E)
checkfile
echo "Editing $filename file..."
;;
-p|-P)
checkfile
echo "Displaying $filename file..."
;;
*)
echo "Bad argument!"
echo "Usage: `basename $0` -e|-p filename"
echo " -e filename : Edit file."
echo " -f filename : Display file."
;;
esac
处理过程中,一下shell内置参数命令如下:
* $0 :即命令本身,相当于c/c++中的argv[0]
* $1 :第一个参数.
* $2, $3, $4 ... :第2、3、4个参数,依次类推。
* $# 参数的个数,不包括命令本身
* $@ :参数本身的列表,也不包括命令本身
* $* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"以IFS(默认为空格)来划分字段,如果空格在“”里面,不划分。举例如下:
Listing args with"$*":
Arg #1=1 2 3 4
所有的参数被认为是一个单词
Listing args with "$@":
Arg #1=1
Arg #2=2
Arg #3=3
Arg #4=4
所有的参数被认为是各个独立的单词
Listing args with $* (未被引用):
Arg #1=1
Arg #2=2
Arg #3=3
Arg #4=4
getopts 的特点:
getopts 会识别所有这些选项格式,指定的选项可以是大写或小写字母,或是数字。虽然它也能识别其他字符,但是不推荐使用。通常情况下,在处理命令行选项和参数时,我们需要多次调用 getopts。getopts 本身不会更改位置参数的设置,如果我们想要将位置参数移位,必须仍使用 shift 命令来处理位置参数。因为当没有内容可以解析时,getopts 会设置一个退出状态 FALSE,所以它很容易在 while 循环中使用:
while getopts ...; do
...
done
getopts 将解析选项和它们可能的参数。它将在第一个非选项参数(不以连字符“-”开头的,且不是它前面的任何选项的参数的字符串)的位置停止解析。当遇到双连字符“--”(表示选项的结束)时,它也将停止解析。
getopts 会使用到如下 3 个变量:
getopts 命令的基本语法:
getopts OPTSTRING VARNAME [ARGS...]
例如,如下的命令告诉 getopts 查找 -f、-A 和 -x 选项:
getopts fAx VARNAME
而下面的命令告诉 getopts -A 选项后面会有一个参数:
getopts fA:x VARNAME
默认情况下 getopts 命令是解析当前 Shell 或函数的位置参数。我们可以指定自己的参数让 getopts 来解析。一旦额外的参数指定在了 VARNAME 之后,getopts 将不再尝试解析位置参数,而是解析这些额外指定的参数。
getopts 命令还支持两种错误报告的模式,分别为:详细错误报告模式和抑制错误报告模式。对于产品中的脚本,推荐使用抑制错误报告模式,因为这样看起来更专业,不会看到恼人的标准信息。同样它也更容易处理,因为我们以更简单的方法显示了失败的情况。
在详细错误报告模式下,如果 getopts 遇到了一个无效的选项,VARNAME 的值会被设置为问号(?),并且变量 OPTARG 不会被设置;如果需要的参数没有找到,VARNAME 的值同样会被设置为问号(?),变量 OPTARG 也不会被设置,并且会打印一个错误信息。
在抑制错误报告模式下,如果 getopts 遇到了一个无效的选项,VARNAME 的值会被设置为问号(?),并且变量 OPTARG 会被设置为选项字符;如果需要的参数没找到,VARNAME 的值同样会被设置为冒号(:),并且变量 OPTARG 中会包含选项字符。
#安全CP实现
while getopts ":adpfiRr" opt
do
case $opt in
a)
echo "option a"
exit
;;
esac
case $opt in
?)
;;
esac
done
#移动到参数位置
shift $[ $OPTIND -1 ]
#处理参数
while [ $# -gt 1 ]
do
src="${src} $1"
shift
done
dst=$1
getopt 命令与 getopts 的功能很相似,也是用于解析命令行的选项和参数,使其可以被 Shell 程序简单地解析。不同的是,getopt 命令是 Linux 下的命令行工具,并且 getopt 支持命令行的长选项(比如,--some-option)。另外,在脚本中它们的调用方式也不同。getopt 的语法类似如下:
getopt [options] [--] optstring parameters
getopt [options] -o|--options optstring [options] [--] parameters
下面是一个示例:
$ getopt f:vl -vl -f/local/filename.conf param_1
-v -l -f /local/filename.conf -- param_1
上例中,“f:vl” 对应 getopt 命令语法中的 optstring(选项字符串),“-vl -f/local/filename.conf param_1” 对应 getopt 命令语法中的 parameters(getopt 命令的参数)。因此,getopt 会按照 optstring 的设置,将 parameters 解析为相应的选项和参数。所以,“-vl” 被解析为了 “-v” 和 “-l”。与 getopts 类似,因为在选项字符串中 “f” 后有一个冒号(:),所以 “-f/local/filename.conf” 被解析为 “-f /local/filename.conf”。然后解析后的命令行选项和参数之间使用双连字符(--)分隔。
tgt_flag=false
#增加了eval后,选项参数可用,否则参数为‘param’形式
eval set -- `getopt -o t:S:Z:: -l target:,backup::,suffix:,preserve::,reflink::,sparse:,no-preserve:,context:: -- "$@" 2>/dev/null`>/dev/null 2>&1
while [ $# -gt 0 ]
do
case $1 in
-t|--target)
tgt_flag=true
dst=$2
shift 2
;;
#必接参数的,偏移2位
-S|--no-preserve|--sparse|--suffix)
shift 2
;;
?)
shift
;;
#--表示选项结束,剩下的是参数。
--)
shift
break
;;
esac
done
if ${tgt_flag}
then
src=$*
else
while [ $# -gt 1 ]
do
src="${src} $1"
shift
done
dst=$1
fi
getopt 命令遵循如下规则: