使用位置参数和1个命名参数的组合

时间:2016-02-07 16:09:15

标签: linux bash shell unix getopts

我仍在使用这些功能“烘焙”我的外壳所以我的问题可能听起来不像“完全准备好”..更多的是“什么是最好的设计方式”,而不是“我碰到了这个错误或者这不会工作..现在我该怎么做“,所以请耐心等待。我解释时 我正在考虑一个可以在2种模式下运行的shell程序

  • 标准模式是一堆位置参数
    例如myprogram date1 date2 date3 date4 # can go on indefinitely
  • 命名参数模式
    myprogram -r date1 # Just 1 date para allowed

他们当然互相排斥myprogram date1 date2 date3 date4是好的 myprogram -r date1 date2 date3 date4不是因为-r

预计只有1个参数

我知道getopts提供了一个命名参数功能,可以shift通过一堆选项。
我已准备好标准模式&工作并希望“添加”代码以获得命名参数模式
在标准模式下,我的代码的图案类似于

for args
do
stuff that I want done here 
shift
done

所以这就是我想要的命名参数模式逻辑
(当我使用getopts以及更多使用1个位置参数时它应该退出。)
由于getopts只允许1个参数,我想的是这样的一些

while getopts "r:"  opt; 
do
case statement of getopts 
<stuff I want to do >
esac 
done


并且为了将位置限制为1,我应该有这样的东西?
[ "$#" -eq 2 ] || die " more than 1 para not expected here"
2是因为当我在上面的while循环中时,-r是第一个pos。 para和1 para是进入那里的变量。我必须在循环中进行检查,因为如果不使用-r选项,我希望它没有任何操作,在这种情况下,我可以拥有尽可能多的pos参数
所以我如何做到最好 - 这是我想要了解的。 将getopts代码置于第1位,然后使用位置参数代码进行操作? 对不起,如果我的问题太具体了。

2 个答案:

答案 0 :(得分:2)

我并不总是使用getopts,但是当我这样做时,它看起来像这样:

...

#Defaults
Verbose=false
ropt=false

# Options
while getopts vr: opt; do
  case "$opt" in
    v)  Verbose=true; vopt="-v" ;;
    r)  ropt=true; rarg="$OPTARG" ;;
    *)  usage; exit 1 ;;
  esac
done
shift $((OPTIND - 1))

if $ropt && [ $# -gt 0 ]; then
  $Verbose && echo "Too many arguments. Bye." >&2
  exit 1
elif $ropt; then
  args=( "$rarg" )
else
  args=( "$@" )
fi

# then...
for thing in "$args"; do
  ... something with $thing ...
done

getopts循环后的第一个条件控制您是以多参数还是单参数(-r)模式运行。随后的else填充$args数组,然后您可以随后执行任何操作。

答案 1 :(得分:1)

我使用getopts代替getopt,但我认为逻辑是相同的。循环遍历命名选项,然后一旦完成,如果您还没有设置选项,只需使用其余选项。

ARGS=$(getopt --options=r: --name="$0" -- "$@");
if [ $? -ne 0 ]; then
    echo_usage
    exit 1
fi

eval set -- "$ARGS";

while true; do
    case $1 in
        -r)
            shift
            date1=$1
        ;;
done

if [ -z "$date1" -a ! -z "$1" ]; then
    date1=$1
fi