我需要test.sh
按以下方式调用 shell 脚本:
./test.sh -run/-rerun username password
如何检查它们是否已通过-run
或-rerun
在我的 shell 脚本中选项?
答案1
一个常见的方法是使用getopt
用于分解传递给脚本的命令行选项以便于解析的实用程序。getopt
支持带或不带参数的短(单字符)和长(多字符)选项。getopt
调用时会传递两种参数:修改getopt
将解析选项的方式的选项,以及要解析的调用脚本的参数。
指定如何解析剩余参数的最重要选项getopt
如下:
-o, --options shortopts
要解析的短选项。该选项的参数shortopts
是一个字符串,应被识别为短选项。带有必需参数的选项字符后应跟一个冒号:
,而带有可选参数的选项后应跟两个冒号::
。例如,该shortopts
字符串ab:c::
对应于以下识别的选项-a
、-b arg
和-c
。-c arg
请注意,如果未指定此选项,则会将第一个不以(并且不是选项参数)getopt
开头的选项视为字符串。-
shortopts
-l, --longoptions longopts
要解析的长选项。可以一次指定多个选项,用逗号分隔选项名称,或者-l
可以多次给出该选项。必需和可选参数通过选项名称后带有或的-o
选项来指示。:
::
-a, --alternative
一个共同的约定,尤其是GNU软件的一个缺点是长选项前面有两个破折号,例如--run
。该-a
选项指示getopt
允许长选项以单个-
字符开头。-q,--quiet
如果getopt
在要解析的参数中遇到无法识别的选项或缺少必需的参数,它将打印一条getopt: unrecognized option '[option name]'
或getopt: option '[option name'] requires an argument
to形式的消息stderr
,生成正常输出 tostdout
并以非零状态退出。该-q
选项可用于抑制错误消息。-n, --name progname
该选项可用于指定getopt
报告上述错误时将使用的程序名称。
第一个非选项参数(不是选项参数或shortopts
如上所述被视为字符串)被视为getopt
要解析的参数列表的开始。这些参数的开始也可以用 指示--
,在这种情况下,后面的第一个参数--
被视为要解析的参数列表的开始。
of 的正常输出getopt
是已识别选项的扩展列表,如下所示:
一起给出的短选项,例如
-abc
,被扩展为单独的选项,即-a -b -c
。如果
-a
指定为 的选项getopt
,则以单个破折号开头的长选项(例如-foo
)会以附加破折号作为前缀,即--foo
。选项的必需参数和可选参数被引用,例如,
-b arg
becomes和become 。-b 'arg'
--foo arg
--foo=arg
--foo 'arg'
任何剩余的参数都被引用并与选项分隔开
--
。
扩展的优点是更容易解析分解的选项,因为需要考虑的情况较少。getopt
下面给出了使用问题中指定的命令行选项解析的示例:
#!/bin/bash
OPTS=`getopt -a -l run -l rerun -- "$0" "$@"`
if [ $? != 0 ] # There was an error parsing the options
then
exit 1
fi
eval set -- "$OPTS"
while true; do
case "$1" in
--run) echo "option --run specified"; shift;;
--rerun) echo "option --rerun specified"; shift;;
--) shift; break;;
esac
done
echo "Args:"
for arg # Process remaining arguments
do
echo $arg
done
解释:
OPTS=`getopt -a -l run -l rerun -- "$0" "$@"`
这里我们设置OPTS
变量来保存调用的输出getopt
。在本例中,传递到此处的参数getopt
是 shell 设置的内置变量。bash
保存$0
脚本的名称并$@
保存传递给脚本的所有命令行参数(单独引用)。getopt
将根据指定的选项处理参数。在此示例中,将识别不带参数的getopt
长选项--run
。--rerun
由于该-a
选项getopt
还将识别表格-run
和-rerun
。调用的结果getopt
是扩展的参数列表。例如,诸如 之类的脚本调用test.sh -run username password
会被 shell 扩展为getopt
调用getopt -a -l run -l rerun -- "test.sh" "-run" "username" "password"
。getopt
依次输出扩展后的参数--run -- 'username' 'password'
。
if [ $? != 0 ] # There was an error parsing the options
then
exit 1
fi
内置变量$?
保存最近执行的命令的返回值。非零返回值表示getopt
遇到错误。
eval set -- "$OPTS"
这实际上将用 . 输出的扩展参数替换传递给脚本的原始命令行参数getopt
。
while true; do
case "$1" in
--run) echo "option --run specified"; shift;;
--rerun) echo "option --rerun specified"; shift;;
--) shift; break;;
esac
done
$1
循环将从第一个位置参数开始依次处理每个位置参数。扩展后getopt
,只需考虑三种情况。在处理结束时,每种情况shift
都会改变位置参数,使得$2
变为$1
,$3
变为$2
等等。因此,位置参数$1
将在循环的每次迭代中保存一个新值。
如果正在处理的选项需要一个必需的参数,则可以case
通过位置参数在语句中访问该参数值$2
。当选项及其参数被处理后,位置参数需要移动 2 才能摆脱这两个选项和的论点。
当在已识别选项之后、剩余参数之前getopt
输出 a 时, case 表示选项列表的结尾和循环的终止条件。--
--
while
echo "Args:"
for arg # Process remaining arguments
do
echo $arg
done
for arg
是 的缩写for arg in "$@"
。请注意,在while
循环之后,由于shift
每种情况,现在仅保存输出中$@
后面的剩余参数。--
getopt