问题描述
在请求一些参数 (arg) 和选项 (-a) 的脚本中,我想让脚本用户可以将选项放在命令行中他想要的位置。
这是我的代码:
while getopts "a" opt; do
echo "$opt"
done
shift $((OPTIND-1))
echo "all_end : $*"
有了这个命令,我就有了预期的行为:
./test.sh -a arg
a
all_end : arg
我想用这个命令得到相同的结果:
./test.sh arg -a
all_end : arg -a
解决方法
getopt
命令(util-linux
包的一部分,与 getopts
不同)将执行您想要的操作。 bash faq 对使用它有一些意见,但老实说,现在大多数系统都将拥有 getopt
的现代版本。
考虑以下示例:
#!/bin/sh
options=$(getopt -o o: --long option: -- "$@")
eval set -- "$options"
while :; do
case "$1" in
-o|--option)
shift
OPTION=$1
;;
--)
shift
break
;;
esac
shift
done
echo "got option: $OPTION"
echo "remaining args are: $@"
我们可以这样称呼它:
$ ./options.sh -o foo arg1 arg2
got option: foo
remaining args are: arg1 arg2
或者像这样:
$ ./options.sh arg1 arg2 -o foo
got option: foo
remaining args are: arg1 arg2
,
您仍然可以通过查看每个参数来解析参数
#!/bin/bash
for i in "$@"
do
case $i in
-a)
ARG1="set"
shift
;;
*)
# the rest (not -a)
ARGS="${ARGS} $i"
;;
esac
done
if [ -z "$ARG1" ]; then
echo "You haven't passed -a"
else
echo "You have passed -a"
fi
echo "You have also passed: ${ARGS}"
然后你会得到:
> ./script.sh arg -a
You have passed -a
You have also passed: arg
> ./script.sh -a arg
You have passed -a
You have also passed: arg
> ./script.sh -a
You have passed -a
You have also passed:
> ./script.sh arg
You haven't passed -a
You have also passed: arg
,
考虑这种方法
#!/bin/bash
opt(){
case $1 in
-o|--option) option="$2";;
-h|--help ) echo "$help"; exit 0;;
*) echo "unknown option: $1"; exit 1;;
esac
}
while [[ $@ ]]; do
case $1 in
arg1) var1=$1 ;;
arg2) var2=$1 ;;
-*) opt "$@"; shift;;
*) echo "unknown option: $1"; exit 1;;
esac
shift
done
echo args: $var1 $var2
echo opts: $option