Linux中利用getopt和getopts处理选项和参数_getopt --参数-程序员宅基地

技术标签: getopts  bash shell  

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

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Michael177/article/details/123599056

智能推荐

统计平均分:从文本读取成绩并计算平均分,将平均分写入文本文件保存_包含学生考试成绩的源文本文件中提取并计算平均分-程序员宅基地

文章浏览阅读1.2k次。从文本读取成绩并计算平均分,将平均分写入文本文件保存。【学习的细节是欢悦的历程】Python官网Free:大咖免费“圣经”教程python 完全自学教程,不仅仅是基础那么简单……自学并不是什么神秘的东西,一个人一辈子自学的时间总是比在学校学习的时间长,没有老师的时候总是比有老师的时候多。——华罗庚HOT好文力荐从文本读取成绩并计算平均分统计平均分(将平均分写入文本文件保存)本文质量分:90目 录。_包含学生考试成绩的源文本文件中提取并计算平均分

[Intensive Reading]MOT:FairMOT_fairmot实现mot评估-程序员宅基地

文章浏览阅读2.1k次,点赞5次,收藏10次。简介《FairMOT:A Simple Baseline for Multi-Object Tracking》是一个online的多目标跟踪(MOT)算法,基于TBD(Traking-by-Detection)的策略,FairMOT主要就是基于JDE做的改进,可以简单的理解为,FairMOT是将JDE的YOLOv3的主干,改成了CenterNet,也就是将检测的方法由Anchor-base换成了Anchor-free,然后同样在已有检测模型上加了了embeeding分支,模型输出检测的结果和embeedi_fairmot实现mot评估

VS 2008 显示代码行数/改变程序格式风格_vs2008显示行数-程序员宅基地

文章浏览阅读3.9k次。VS 2008 显示代码行数:开发环境C#,其他类同操作。工具-》选项-》文本编辑器-》C#里的显示“行号”勾上即可。-------------------------------------------------------------------------------------------------------改变VS程序风格:java风格: private v_vs2008显示行数

Web前端设计全方位解析:面试题总结+答案详解_前端实现填空题-程序员宅基地

文章浏览阅读1.5k次,点赞21次,收藏29次。面试习题大总结,进来免费白嫖啦_前端实现填空题

0043期基于python的CNN训练识别吃的-含数据集-程序员宅基地

文章浏览阅读681次,点赞19次,收藏14次。083基于深度学习的手势识别小程序版本_含10多种模型包括alexnet、DenseNet、DLA、GoogleNet、Mobilenet、ResNet、ResNeXt、ShuffleNet、VGG、EfficientNet和Swin transformer等10多种模型。117nlp自然语言处理-文本情感分类-joy-sadness-anger-fear-love-surprise。运行02深度学习模型训练.py就会将txt文本中记录的训练集和验证集进行读取训练,训练好后会保存模型在本地。

如何使用 Workbench 远程连接到 MySQL 数据库 -MySQL Workbench 使用教程_mysql workbench连接数据库-程序员宅基地

文章浏览阅读1.5w次,点赞12次,收藏88次。MySQL Workbench 是一款专门为 MySQL 设计的可视化数据库 GUI 管理工具,我们可以在自己的计算机上,使用图形化界面(GUI)远程管理 MySQL 数据库。有关 MySQL 远程管理软件,你可以选择 Windows 下的 HeidiSQL,MacOS 下的 Sequel Ace 或者 MySQL 官方推出的跨平台客户端 MySQL Workbench 。如果你需要针对自己的工作流对数据库操作,定制开发,推荐一下卡拉云,详情见文末。本._mysql workbench连接数据库

随便推点

linux catalina.sh java_opts,Tomcat启动脚本catalina.sh---解读-程序员宅基地

文章浏览阅读1k次。原网址:http://blog.csdn.net/sun8288/article/details/78431271 - 概述脚本catalina.sh用于启动和关闭tomcat服务器,是最关键的脚本另外的脚本startup.sh和shutdown.sh都是使用不同的参数调用了该脚本该脚本的使用方法如下(引自该脚本本身):echo "Usage: catalina.sh ( commands ......_catalina.sh java_opts

【算法题】一种字符串压缩表示的解压(js)-程序员宅基地

文章浏览阅读100次。全部由小写英文字母组成,压缩后不会出现@,故输出不合法。两个d不需要压缩,故输入不合法。_一种字符串压缩表示的解压

matplotlib将figure转化为numpy的array矩阵格式_manager.canvas.figure转换成array-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏10次。最近碰到一个问题,python读入视频,并处理每一张图片,并将处理的结果用quiver显示为矢量图,然后将矢量图转化为numpy数据。在这整个过程中碰到以下问题:1)怎么使用quiver,这个用起来有很多参数需要设置,没有MATLAB用起来方便,不过这个不是本博文的重点。2)怎么将矢量图的效果转化为numpy数据,这个我在百度上搜索了好多博文,但是都不是我想要的效果,当我科学上网时,发现matplotlib有官方的介绍,这里贴出链接3)成功的转化为numpy后,又发现我的数据又多了轴参数,致使整个_manager.canvas.figure转换成array

机器学习与数据挖掘-实验二_《机器学习与数据挖掘》实验二-程序员宅基地

文章浏览阅读1.1k次。1. 根据给定数据集(存放在data1.txt文件中,二分类数据),编码实现基于梯度下降的Logistic回归算法,画出决策边界;2. 从UCI中选择鸢尾花数据集(多分类数据),使用Sklearn实现Logistic回归;实现第一个决策边界的代码如下:(注意格式)import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn import linear_modelfrom sklearn._《机器学习与数据挖掘》实验二

扔掉工具类,Mybatis 一个简单配置搞定数据加密解密!-程序员宅基地

文章浏览阅读185次。前言:介绍一个简单的MyBatis加解密方式,日常学习工作中提及这种方法的比较少,所以拿来说说,如果已经知道这种方法的忽略本文!一、背景在我们数据库中有些时候会保存一些用户的敏感信息,比如:手机号、银行卡等信息,如果这些信息以明文的方式保存,那么是不安全的。假如:黑客黑进了数据库,或者离职人员导出了数据,那么就可能导致这些敏感数据的泄漏。因此我们就需要找到一种方法来解决这个问题。二、解决方案由于我..._mybatis-flex 数据加解密

女生适不适合进入IT行业做Linux运维工程师?-程序员宅基地

文章浏览阅读2.4k次。 不知从何时起有那么一个不成文的理论:女生不适合做IT。在很多人看来,IT is a men’s world,女生学IT是件匪夷所思的事情。在传统的思维当中..._linux推不推荐入行

推荐文章

热门文章

相关标签