我想设计一个shell脚本作为一对脚本的 Package 器。我想使用getopts
为myshell.sh
指定参数,并将其余参数以相同的顺序传递给指定的脚本。
如果myshell.sh
按如下方式执行:
myshell.sh -h hostname -s test.sh -d waittime param1 param2 param3
myshell.sh param1 param2 -h hostname param3 -d waittime -s test.sh
myshell.sh param1 -h hostname -d waittime -s test.sh param2 param3
以上所有内容都应该能够调用为
test.sh param1 param2 param3
是否可以利用myshell.sh
中的选项参数并将其余参数发布到基础脚本?
9条答案
按热度按时间gajydyqb1#
我想做一些与OP类似的事情,我找到了我需要的相关信息here和here
基本上,如果您想执行以下操作:
然后得到你的选择像这样:
然后你就可以得到这样的位置论证:
更多信息和细节可通过上面的链接。
0tdrvxhp2#
myshell.sh:
test.sh:
测试OP用例:
发生了什么:
如果
getopts
遇到位置参数,它将失败。如果它被用作循环条件,则每当位置参数出现在选项之前时,循环就会过早中断,就像在两个测试用例中一样。因此,这个循环只有在所有参数都处理完之后才会中断,如果
getopts
没有识别出某个参数,我们就假设它是一个位置参数,并将其填充到数组中,同时手动递增getopts
的计数器。可能的改进:
正如所写的那样,子脚本不能接受选项(仅位置参数),因为 Package 器脚本中的
getopts
将吃掉这些选项并打印错误消息,同时将任何参数视为位置参数:如果我们知道子脚本只能接受位置参数,那么
myshell.sh
可能会在一个无法识别的选项上停止,这可以像在case
块的末尾添加一个默认的last case一样简单:如果子脚本需要接受选项(只要它们不与
myshell.sh
中的选项冲突),我们可以通过在选项字符串前添加冒号将getopts
切换到静默错误报告:然后我们使用默认的最后一个case将任何无法识别的选项填充到
script_args
中:idfiyjo83#
混合选项和参数:
结果:
km0tfn4u4#
getopts
不会解析param1
和-n
选项的混合。把param 1 -3像其他一样放进选项里要好得多。
此外,您可以使用已经存在的库,如shflags。它非常智能,也很容易使用。
最后一种方法是编写自己的函数来解析参数,而不使用getopt,只是通过
case
构造来迭代所有参数,这是最困难的方法,但也是唯一完全符合预期的方法。l2osamch5#
我想出了一种扩展
getopts
以真正混合选项和位置参数的方法,其思想是在调用getopts
和将找到的任何位置参数赋给n1
、n2
、n3
等之间交替:那么在OP的情况下,您可以像这样使用它:
运行它会显示输出:
只是个概念验证,但也许对某人有用。
注意:如果一个使用
parse_args
的函数调用另一个使用parse_args
的函数并且外部函数声明了local n4=''
,但内部函数没有声明并且4个或更多位置参数传递给内部函数,则会出现问题9w11ddsr6#
只是简单地混合了一个选项和位置参数的混合体(只在$@中留下位置参数):
输出示例:
wpx232ag7#
不使用
getopts
,你可以直接实现你自己的bash参数解析器,以这个为例,它可以同时处理名称和位置参数。您可以将此函数称为:
用法示例:
参考文献:
rdlzhqv98#
unix选项处理有一些标准,在shell编程中,
getopts
是执行这些标准的最好方法,几乎所有的现代语言(perl,python)都有getopts
的变体。这只是一个简单的例子:
1.每个选项必须以破折号
-
开头,并且必须由单个字符组成。--
开头,后跟一个完整的单词--long_option
。AST KSH工程有一个getopts,它也支持长选项,以一个破折号-
开头的 * 和 * 长选项,如find(1)
。1.选项可能需要也可能不需要参数。
1.任何不以破折号
-
开头的单词都将结束选项处理。1.必须跳过字符串
--
,并将结束选项处理。1.任何剩余的参数都作为位置参数保留。
开放组在
Utility Argument Syntax
上有一个部分Eric Raymond的The Art of Unix Programming has a chapter介绍了传统unix中选项字母的选择及其含义。
fruv7luv9#
你可以试试这个把戏:使用optargs执行while循环后,只需使用以下代码片段
但是,这种方法有一个缺陷:
第一个位置参数之后的所有选项都被getopts取反,并被视为位置参数-正确的事件(参见示例输出:-m和-c属于位置参数)
也许它有更多的虫子...
看看整个例子:
输出: