Bash 使用单个必需参数获取多个标志
Bash getopts multiple flags with single required parameter
我无法思考如何让 getopts 通过一个参数接受多个标志。例如。
标记:Children:a - Adam b - Beth c - Cathy d - Duncan
必填参数:冰淇淋口味
(不是我的脚本真正做的,但最容易拼写出来)
我现在能做的:
./flavor -a chocolate
./flavor -c chocolate
我想做什么:
./flavor -acd chocolate
而不是到目前为止我唯一能让它做的事情:
./flavor -a chocolate -c chocolate -d chocolate
我尝试使用 getopts 的每个变体要么根本看不到参数,要么在每个标志声明之后都需要它。我觉得我错过了一些明显的东西,这些东西会给我 "aha" 时刻,但我自己并没有看到它。谁能指出我正确的方向?
============================================
while getopts ":a:b:c:d:" opt; do
case $opt in
a)
do stuff with $OPTARG
;;
b)
do stuff with $OPTARG
;;
c)
do stuff with $OPTARG
;;
d)
do stuff with $OPTARG
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
============================================
如果这是一个非常愚蠢的问题,我深表歉意,感谢您抽出宝贵时间。
有点棘手的方法是:
#!/bin/bash
while getopts ":abcdf:" opt; do
case $opt in
f)
FLAVOUR="$OPTARG"
if [ ${ADAM_IN:-0} -eq 1 ]
then
echo "Adam gets $FLAVOUR"
ADAM_IN=0
fi
if [ ${BETH_IN:-0} -eq 1 ]
then
echo "Beth gets $FLAVOUR"
BETH_IN=0
fi
if [ ${CATHY_IN:-0} -eq 1 ]
then
echo "Cathy gets $FLAVOUR"
CATHY_IN=0
fi
if [ ${DUNCAN_IN:-0} -eq 1 ]
then
echo "Duncan gets $FLAVOUR"
DUNCAN_IN=0
fi
;;
a)
ADAM_IN=1
;;
b)
BETH_IN=1
;;
c)
CATHY_IN=1
;;
d)
DUNCAN_IN=1
;;
:)
echo "invalid argument" 2>/dev/null
exit 1
;;
esac
done
将脚本另存为 ice_cream_allocator
和 运行 如下:
$ ./ice_cream_allocator -abcf"Chocolate" -df"Vanila" -cf"Strawberry"
输出
Adam gets Chocolate
Beth gets Chocolate
Cathy gets Chocolate
Duncan gets Vanila
Cathy gets Strawberry
好吧,我对 Cathy 情有独钟,所以给了她两种口味 ;)
getopts 不支持需要参数的堆叠选项。您只能堆叠不带参数的选项。
要实现您的建议,参数处理需要更加复杂。本质上,您必须预处理选项以找出非选项参数的开始位置。这不是特别漂亮或不推荐,但这确实可以满足您的要求,而无需其他选项:
_GETOPTS=":abcd"
while getopts "${_GETOPTS}" opt
do
case $opt in
abcd)
:
;;
\?)
echo "Unsupported option (-${OPTARG})" >&2
exit 1
;;
esac
done
eval "FIRSTARG=${${OPTIND}}"
if [ -z "${FIRSTARG}" ]
then
echo "Flavor argument required."
exit 1
fi
OPTIND=1
while getopts "${_GETOPTS}" opt
do
case $opt in
a)
echo do a stuff with ${FIRSTARG}
;;
b)
echo do b stuff with ${FIRSTARG}
;;
c)
echo do c stuff with ${FIRSTARG}
;;
d)
echo do d stuff with ${FIRSTARG}
;;
esac
done
结果:
$ ./flavor -acd chocolate
do a stuff with chocolate
do c stuff with chocolate
do d stuff with chocolate
可以在第一个非选项参数之后访问其他参数,但这需要更多的工作。
请注意,在多个 getopts 语句中处理同一组选项很容易产生长期维护问题,因为对于由两个 [= =22=]case 语句不同步。
我无法思考如何让 getopts 通过一个参数接受多个标志。例如。
标记:Children:a - Adam b - Beth c - Cathy d - Duncan
必填参数:冰淇淋口味
(不是我的脚本真正做的,但最容易拼写出来)
我现在能做的:
./flavor -a chocolate
./flavor -c chocolate
我想做什么:
./flavor -acd chocolate
而不是到目前为止我唯一能让它做的事情:
./flavor -a chocolate -c chocolate -d chocolate
我尝试使用 getopts 的每个变体要么根本看不到参数,要么在每个标志声明之后都需要它。我觉得我错过了一些明显的东西,这些东西会给我 "aha" 时刻,但我自己并没有看到它。谁能指出我正确的方向?
============================================
while getopts ":a:b:c:d:" opt; do
case $opt in
a)
do stuff with $OPTARG
;;
b)
do stuff with $OPTARG
;;
c)
do stuff with $OPTARG
;;
d)
do stuff with $OPTARG
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
============================================
如果这是一个非常愚蠢的问题,我深表歉意,感谢您抽出宝贵时间。
有点棘手的方法是:
#!/bin/bash
while getopts ":abcdf:" opt; do
case $opt in
f)
FLAVOUR="$OPTARG"
if [ ${ADAM_IN:-0} -eq 1 ]
then
echo "Adam gets $FLAVOUR"
ADAM_IN=0
fi
if [ ${BETH_IN:-0} -eq 1 ]
then
echo "Beth gets $FLAVOUR"
BETH_IN=0
fi
if [ ${CATHY_IN:-0} -eq 1 ]
then
echo "Cathy gets $FLAVOUR"
CATHY_IN=0
fi
if [ ${DUNCAN_IN:-0} -eq 1 ]
then
echo "Duncan gets $FLAVOUR"
DUNCAN_IN=0
fi
;;
a)
ADAM_IN=1
;;
b)
BETH_IN=1
;;
c)
CATHY_IN=1
;;
d)
DUNCAN_IN=1
;;
:)
echo "invalid argument" 2>/dev/null
exit 1
;;
esac
done
将脚本另存为 ice_cream_allocator
和 运行 如下:
$ ./ice_cream_allocator -abcf"Chocolate" -df"Vanila" -cf"Strawberry"
输出
Adam gets Chocolate
Beth gets Chocolate
Cathy gets Chocolate
Duncan gets Vanila
Cathy gets Strawberry
好吧,我对 Cathy 情有独钟,所以给了她两种口味 ;)
getopts 不支持需要参数的堆叠选项。您只能堆叠不带参数的选项。
要实现您的建议,参数处理需要更加复杂。本质上,您必须预处理选项以找出非选项参数的开始位置。这不是特别漂亮或不推荐,但这确实可以满足您的要求,而无需其他选项:
_GETOPTS=":abcd"
while getopts "${_GETOPTS}" opt
do
case $opt in
abcd)
:
;;
\?)
echo "Unsupported option (-${OPTARG})" >&2
exit 1
;;
esac
done
eval "FIRSTARG=${${OPTIND}}"
if [ -z "${FIRSTARG}" ]
then
echo "Flavor argument required."
exit 1
fi
OPTIND=1
while getopts "${_GETOPTS}" opt
do
case $opt in
a)
echo do a stuff with ${FIRSTARG}
;;
b)
echo do b stuff with ${FIRSTARG}
;;
c)
echo do c stuff with ${FIRSTARG}
;;
d)
echo do d stuff with ${FIRSTARG}
;;
esac
done
结果:
$ ./flavor -acd chocolate
do a stuff with chocolate
do c stuff with chocolate
do d stuff with chocolate
可以在第一个非选项参数之后访问其他参数,但这需要更多的工作。
请注意,在多个 getopts 语句中处理同一组选项很容易产生长期维护问题,因为对于由两个 [= =22=]case 语句不同步。