Bash : 使用 getopts 解析参数后的选项
Bash : Parse options after arguments with getopts
在请求一些参数 (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 "" in
-o|--option)
shift
OPTION=
;;
--)
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 in
-o|--option) option="";;
-h|--help ) echo "$help"; exit 0;;
*) echo "unknown option: "; exit 1;;
esac
}
while [[ $@ ]]; do
case in
arg1) var1= ;;
arg2) var2= ;;
-*) opt "$@"; shift;;
*) echo "unknown option: "; exit 1;;
esac
shift
done
echo args: $var1 $var2
echo opts: $option
在多年的 bash 编程中,我发现摆脱脑海中认为函数应该看起来像 f(x,y) 的骨头很有用,尤其是自从 bash 需要 clumsy/inefficient 代码来处理命令行参数。
选项参数通常有默认值,可以更容易地作为环境变量传递,其范围仅限于被调用的脚本,并保存必须提供的参数。
将此应用于您的示例,脚本如下所示:
OPTION=${OPTION:="fee"}
echo "option: $OPTION"
echo "remaining args are: $*"
并且会被调用:
OPTION="foo" ./options.sh arg1 arg2
在请求一些参数 (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 "" in
-o|--option)
shift
OPTION=
;;
--)
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 in
-o|--option) option="";;
-h|--help ) echo "$help"; exit 0;;
*) echo "unknown option: "; exit 1;;
esac
}
while [[ $@ ]]; do
case in
arg1) var1= ;;
arg2) var2= ;;
-*) opt "$@"; shift;;
*) echo "unknown option: "; exit 1;;
esac
shift
done
echo args: $var1 $var2
echo opts: $option
在多年的 bash 编程中,我发现摆脱脑海中认为函数应该看起来像 f(x,y) 的骨头很有用,尤其是自从 bash 需要 clumsy/inefficient 代码来处理命令行参数。
选项参数通常有默认值,可以更容易地作为环境变量传递,其范围仅限于被调用的脚本,并保存必须提供的参数。
将此应用于您的示例,脚本如下所示:
OPTION=${OPTION:="fee"}
echo "option: $OPTION"
echo "remaining args are: $*"
并且会被调用:
OPTION="foo" ./options.sh arg1 arg2