Bash getopts使用单个必需参数选择多个标志

Bash getopts使用单个必需参数选择多个标志,bash,getopts,Bash,Getopts,我很难理解如何让getopts用一个参数接受多个标志。比如说 旗帜:孩子们:a-亚当b-贝丝c-凯西d-邓肯 所需参数:冰淇淋口味 (不是我的脚本真正做的,但最容易用这种方式表达出来) 我现在能做的是: ./flavor -a chocolate ./flavor -c chocolate 我想做的是: ./flavor -acd chocolate 而不是我目前唯一能做的事情: ./flavor -a chocolate -c chocolate -d chocolate 我用get

我很难理解如何让getopts用一个参数接受多个标志。比如说

旗帜:孩子们:a-亚当b-贝丝c-凯西d-邓肯

所需参数:冰淇淋口味

(不是我的脚本真正做的,但最容易用这种方式表达出来)

我现在能做的是:

./flavor -a chocolate

./flavor -c chocolate 
我想做的是:

./flavor -acd chocolate
而不是我目前唯一能做的事情:

./flavor -a chocolate -c chocolate -d chocolate
我用getopts尝试的每个变体要么根本看不到参数,要么在每个标志声明之后都需要它。我觉得我错过了一些很明显的东西,这些东西会给我一个“啊哈”的时刻,但我自己并没有看到。谁能给我指出正确的方向吗

============================================

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
============================================

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 -abcf"Chocolate" -df"Vanila" -cf"Strawberry"
输出

Adam gets Chocolate
Beth gets Chocolate
Cathy gets Chocolate
Duncan gets Vanila
Cathy gets Strawberry

好吧,我有一个柔软的角落给凯茜,所以给她两种口味;)

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语句中处理同一组选项容易产生长期维护问题,因为这两个case语句处理的选项很容易失去同步。

您没有遗漏任何内容;没有一种方法可以指定一个参数应该由组中的所有选项共享。我相信你不能这样做,但我可能错了。使用
/flavor-acd
a将使用cd作为其
$OPTARG
。谢谢。这让我有90%的时间可以到达那里。我现在需要弄清楚如何使参数成为必需的,这样就不会遗漏它;然后需要回显味道参数;出口1;是的。工作起来很有魅力!再次感谢。:)我知道你在这里做什么,但当我去简化我的脚本实际在做什么(即,不是冰淇淋)时,这将是不可行的。非常感谢您抽出时间回复并提供帮助。@Mathaen:不客气,祝您好运。:-)