Linux中利用getopt和getopts处理选项和参数

1.使用getpot命令

getopt是一个在处理命令行选项和参数时非常方便的工具。它能够识别命令行参数,从而在脚本中解析更方便。

1.1 命令的格式

getopt命令可以接受任意形式的命令行和参数,并自动将他们转换为适当的格式。
getopt options optstring parameters
optstring定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值。
首先,在optstring中列出你要在脚本中用到的每个命令行选项字母。然后,在每个需要参数值的选项字母后加一个冒号。getopt命令会基于你定义的optstring解析提供的参数。
下面是个getopt如何工作的简单例子。

$ getopt ab:cd -a -b test1 -cd test2 test3
 -a -b test1 -c -d -- test2 test3 
$ 

optstring定义了四个有效选项字母:a、b、c和d。冒号(:)被放在了字母b后面,因为b选项需要一个参数值。当getopt命令运行时,它会检查提供的参数列表(-a -b test1 -cd test2 test3),并基于提供的optstring进行解析。注意,它会自动将-cd选项分成两个单独的选项,并插入双破折线来分隔行中的额外参数。
如果指定了一个不在optstring中的选项,默认情况下,getopt命令会产生一条错误消息。

$ getopt ab:cd -a -b test1 -cde test2 test3
getopt: invalid option -- e 
 -a -b test1 -c -d -- test2 test3 
$ 

如果想忽略这条错误消息,可以在命令后加-q选项。

$ getopt -q ab:cd -a -b test1 -cde test2 test3
 -a -b 'test1' -c -d -- 'test2' 'test3' 
$ 

注意,getopt命令选项必须出现在optstring之前。现在应该可以在脚本中使用此命令处理命令行选项了。

2. 在脚本中使用getopt

方法是用getopt命令生成的格式化后的版本来替换已有的命令行选项和参数。用set命令能够做到。
set命令的选项之一是双破折线(–),它会将命令行参数替换成set命令的命令行值。
然后,该方法会将原始脚本的命令行参数传给getopt命令,之后再将getopt命令的输出传给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数,看起来如下所示。
set -- $(getopt -q ab:cd "$@")
现在原始的命令行参数变量的值会被getopt命令的输出替换,而getopt已经为我们格式化好了命令行参数。

$ cat test18.sh
#!/bin/bash 
# Extract command line options & values with getopt 
# 
set -- $(getopt -q ab:cd "$@") 
# 
echo 
while [ -n "$1" ] 
do 
 case "$1" in 
 -a) echo "Found the -a option" ;; 
 -b) param="$2" 
 echo "Found the -b option, with parameter value $param" 
 shift ;; 
 -c) echo "Found the -c option" ;; 
 --) shift 
 break ;; 
 *) echo "$1 is not an option";; 
 esac
shift 
done 
# 
count=1 
for param in "$@" 
do 
 echo "Parameter #$count: $param" 
 count=$[ $count + 1 ] 
done 

你会注意到它跟脚本test17.sh一样,唯一不同的是加入了getopt命令来帮助格式化命令行参数。现在如果运行带有复杂选项的脚本,就可以看出效果更好了。

$ ./test18.sh -ac
Found the -a option 
Found the -c option 
$ 

当然,之前的功能照样没有问题。

$ ./test18.sh -a -b test1 -cd test2 test3 test4
Found the -a option 
Found the -b option, with parameter value 'test1' 
Found the -c option 
Parameter #1: 'test2' 
Parameter #2: 'test3' 
Parameter #3: 'test4' 
$ 

现在看起来相当不错了。但是,在getopt命令中仍然隐藏着一个小问题。看看这个例子。

$ ./test18.sh -a -b test1 -cd "test2 test3" test4
Found the -a option 
Found the -b option, with parameter value 'test1' 
Found the -c option 
Parameter #1: 'test2 
Parameter #2: test3' 
Parameter #3: 'test4' 
$ 

getopt命令并不擅长处理带空格和引号的参数值。它会将空格当作参数分隔符,而不是根据双引号将二者当作一个参数。幸而还有另外一个办法能解决这个问题。

3 使用更高级的 getopts

每次调用它时,它一次只处理命令行上检测到的一个参数。处理完所有的参数后,它会退出并返回一个大于0的退出状态码。这让它非常适合用解析命令行所有参数的循环中。
getopts命令的格式如下:
getopts optstring variable
optstring值类似于getopt命令中的那个。有效的选项字母都会列在optstring中,如果选项字母要求有个参数值,就加一个冒号。要去掉错误消息的话,可以在optstring之前加一个冒号。getopts命令将当前参数保存在命令行中定义的variable中。getopts命令会用到两个环境变量。如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值。OPTIND环境变量保存了参数列表中getopts正在处理的参数位置。这样你就能在处理完选项之后继续处理其他命令行参数了。
让我们看个使用getopts命令的简单例子。

$ cat test19.sh
#!/bin/bash 
# simple demonstration of the getopts command 
# 
echo 
while getopts :ab:c opt 
do 
 case "$opt" in 
 a) echo "Found the -a option" ;; 
 b) echo "Found the -b option, with value $OPTARG";; 
 c) echo "Found the -c option" ;; 
 *) echo "Unknown option: $opt";; 
 esac 
done 
$ 
$ ./test19.sh -ab test1 -c
Found the -a option 
Found the -b option, with value test1 
Found the -c option

while语句定义了getopts命令,指明了要查找哪些命令行选项,以及每次迭代中存储它们的变量名(opt)。
你会注意到在本例中case语句的用法有些不同。getopts命令解析命令行选项时会移除开头的单破折线,所以在case定义中不用单破折线。
getopts命令有几个好用的功能。对新手来说,可以在参数值中包含空格。

$ ./test19.sh -b "test1 test2" -a
Found the -b option, with value test1 test2 
Found the -a option 
$

另一个好用的功能是将选项字母和参数值放在一起使用,而不用加空格。

$ ./test19.sh -abtest1
Found the -a option 
Found the -b option, with value test1 
$

getopts命令能够从-b选项中正确解析出test1值。除此之外,getopts还能够将命令行上找到的所有未定义的选项统一输出成问号。

$ ./test19.sh -d
Unknown option: ? 
$ 
$ ./test19.sh -acde
Found the -a option 
Found the -c option 
Unknown option: ? 
Unknown option: ? 
$ 

optstring中未定义的选项字母会以问号形式发送给代码。getopts命令知道何时停止处理选项,并将参数留给你处理。在getopts处理每个选项时,它会将OPTIND环境变量值增一。在getopts完成处理时,你可以使用shift命令和OPTIND值来移动参数。

$ cat test20.sh
#!/bin/bash 
# Processing options & parameters with getopts 
# 
echo 
while getopts :ab:cd opt 
do 
 case "$opt" in 
 a) echo "Found the -a option" ;; 
 b) echo "Found the -b option, with value $OPTARG" ;; 
 c) echo "Found the -c option" ;; 
 d) echo "Found the -d option" ;; 
 *) echo "Unknown option: $opt" ;; 
 esac 
done 
# 
shift $[ $OPTIND - 1 ] 
# 
echo 
count=1 
for param in "$@" 
do 
 echo "Parameter $count: $param" 
 count=$[ $count + 1 ] 
done 
$
$ ./test20.sh -a -b test1 -d test2 test3 test4
Found the -a option 
Found the -b option, with value test1 
Found the -d option 
Parameter 1: test2 
Parameter 2: test3 
Parameter 3: test4 
$ 

现在你就拥有了一个能在所有shell脚本中使用的全功能命令行选项和参数处理工具。

4 将选项标准化

在创建shell脚本时,显然可以控制具体怎么做。你完全可以决定用哪些字母选项以及它们的用法。
但有些字母选项在Linux世界里已经拥有了某种程度的标准含义。如果你能在shell脚本中支持这些选项,脚本看起来能更友好一些。
表14-1显示了Linux中用到的一些命令行选项的常用含义。
表14-1 常用的Linux命令选项

选 项描 述
-a显示所有对象
-c生成一个计数
-d指定一个目录
-e扩展一个对象
-f指定读入数据的文件
-h显示命令的帮助信息
-i忽略文本大小写
-l产生输出的长格式版本
-n使用非交互模式(批处理)
-o将所有输出重定向到的指定的输出文件
-q以安静模式运行
-r递归地处理目录和文件
-s以安静模式运行
-v生成详细输出
-x排除某个对象
-y对所有问题回答yes

如果你的选项也采用同样的含义,这样用户在使用你的脚本时就不用去查手册了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值