我正在尝试学习使用bash中的getopts()功能来解析我的参数,但我的程序要求除了我的标准-a -b -c类型参数之外我还需要获取任意数量的文件工作,我找不到任何有关如何使getopts识别它们而不是将它们作为无效参数抛出的信息。这是一个例子:
while getopts "a:b:c:d" flag
do
echo Doing: "$flag" $OPTIND $OPTARG
if [ "$flag" = a ]; then
first="$OPTARG"
echo Found argument: $first
fi
...等等其他if语句。如果我的程序只需要一个命令,例如:program -a -c,那么这很有用,但我需要接受类似的东西:program -a file.sh -c otherfile.sh。
有人可以告诉我一个如何做这样的事情的例子吗?
答案 0 :(得分:2)
以下是我的shell脚本的一个片段,它使用getopts
并且或多或少地按照您的意愿执行:
arg0=$(basename $0 .sh)
usage()
{
echo "Usage: $arg0 [-qvF] [-s suffix] -j jdcfile file.msd" 1>&2
exit 1
}
error()
{
echo "$arg0: $*" 1>&2
exit 1
}
Fflag=
suffix=
jdcfile=
qflag=
vflag=no
while getopts Fj:qs:v opt
do
case "$opt" in
(F) Fflag="-F";;
(j) jdcfile="$OPTARG";;
(q) qflag="-q";;
(s) suffix="$OPTARG";;
(v) vflag=yes;;
(*) usage;;
esac
done
shift $(($OPTIND - 1))
case $# in
(1) : OK;;
(*) usage;;
esac
if [ -z "$jdcfile" ]
then error "you did not specify which jdcfile to use (-j option)"
fi
msd_file=$1
我认为shift
是你缺少的部分。那个以及getopts
处理循环后命令行上剩余参数的后续处理。
在此特定程序的最后,"$@"
中只有一个文件名应该被处理。对于此特定程序,没有列出文件或列出多个文件是错误。您可以删除最终case
或修改它以满足您的需求。此代码还强制执行-j jdcfile
'选项';它是一个强制性参数,如用法消息中所示。
shift
之后的更典型的模式是:
for file in "$@"
do
...processing of $file...
done
这只是让你处理零文件名的情况。
error
和usage
函数也是有用的大纲/原型。如评论中所述,如果您希望在选项字符串上使用前导:
,则可以负责错误处理。我选择不这样做,但我忘记了这是我做出的决定。
答案 1 :(得分:0)
根据我上面的评论 - 您不希望getopts
这样做。一种更简单的方法可行:
#!/bin/bash
args=()
for arg in "$@"
do
case "$arg" in
"-a" )
echo "We have an '-a'!"
;;
"-b" )
echo "We have a '-b'!"
;;
* )
args+=($arg)
esac
done
echo And we have these arguments: ${args[*]}
要看它运行:
$ ./program one -a two three -b four
We have an '-a'!
We have a '-b'!
And we have these arguments: one two three four