不允许在bash脚本的getopts中有多个选项

时间:2021-08-23 07:37:56

Having bash script as follows

有bash脚本如下

#! /bin/bash

usage()
{
  echo -e "need help!"  
}

while getopts ":a:b:h" OPTION
do
     case $OPTION in
     a)
        printf "a option with value %s\n" $OPTARG
        ;;
     b)
        printf "b option with value %s\n" $OPTARG
        ;;
     h)
        usage
        ;;
     ?)
        echo -e "No option selected"
       ;;
    esac
done

exit 0

Above script run fine with different option but i wanted to extend it to not allow to pass multiple option at same time like as following argument

上面的脚本运行正常,有不同的选项,但我想扩展它不允许同时传递多个选项,如下面的参数

$ ./test.bash -a 1 -b 2
a option with value 1
b option with value 2

should be not valid means some way it give me error like wrong syntax i achieved it by as follows but it seems to long it is as follow

应该是无效的意味着某种方式它给我错误像错误的语法我实现它如下,但它似乎很长它如下

#! /bin/bash
usage()
{
  echo -e "need help!"  
}

let "a_count=0"
let "b_count=0"
MY_ARG=""
while getopts ":a:b:h" OPTION
do
     case $OPTION in
     a)
        let a_count=1
        MY_ARG=$OPTARG
        ;;
     b)
        let b_count=1
        MY_ARG=$OPTARG
        ;;
     h)
        usage
        ;;
     ?)
        echo -e "No option selected"
       ;;
    esac
done

[[ $a_count -eq 1 ]] && [[ $b_count -eq 1 ]] && echo "wrong command sytax" && exit 0

[[ $a_count -eq 1 ]] &&  printf "a option with value %s\n" $MY_ARG

[[ $b_count -eq 1 ]] &&  printf "b option with value %s\n" $MY_ARG

exit 0

run like

跑得像

$ ./test.bash -a 1 -b 2
wrong command sytax

But i want to finish validation in while..loop of getopts. Also this validation not works for following command

但我想在while..loop的getopts中完​​成验证。此验证也不适用于以下命令

./test.bash -a -b 
a option with value -b

any one have batter idea how to use getopts for this type validation?

任何人都有击球手的想法如何使用getopts进行此类型验证?

3 个解决方案

#1


1  

you've almost got it. The : after the a and after the b say that they take an argument, so your example with -a -b is actually valid, saying "There is option a with value -b".

你几乎得到了它。 :a之后和之后b表示他们接受了一个参数,所以你的例子-a -b实际上是有效的,说“有选项a带值-b”。

If you really just want "-a or -b and then an argument", you probably don't need getopts at all, but should do:

如果你真的只想要“-a或-b然后一个参数”,你可能根本不需要getopts,但是应该这样做:

[ "$1" == "-a" ] && printf "a option with value %s\n" $2
[ "$1" == "-b" ] && printf "b option with value %s\n" $2

#2


0  

any one have batter idea how to use getopts for this type validation?

任何人都有击球手的想法如何使用getopts进行此类型验证?

well, actually, you're explicitly telling geptopts that -a and -b are not boolean parameters, but parameters that take an extra argument. The argument parser cannot tell whether the argument following -a is a parameter or its own argument, and thus they consider [-a ] [-b ] as syntax.

好吧,实际上,你明确告诉geptopts -a和-b不是布尔参数,而是需要额​​外参数的参数。参数解析器无法判断-a后面的参数是参数还是自己的参数,因此他们将[-a] [-b]视为语法。

The best way, would actually be to have a different boolean parameter that matches the use case when you do not want an argument for -a and -b.

最好的方法,实际上是当你不想要-a和-b的参数时,有一个不同的布尔参数匹配用例。

Though, it won't help you with your issue trying to have parameters with argument or boolean, but for the argument syntax checking you can try docopt which has a nicer way to create command line interface. You focus on doing the --help documentation, it parses it to build your parameter/argument parser. e.g.:

虽然,它不会帮助您尝试使用参数或布尔值的参数,但对于参数语法检查,您可以尝试docopt,它有一个更好的方法来创建命令行界面。您专注于执行--help文档,它会解析它以构建您的参数/参数解析器。例如。:

eval "$(docopts -V - -h - : "$@" <<EOF
Usage: myscript [(-a <foo> | -b <bar> | -abool | -bbool)]

      -a <foo>   The A option.
      -b <bar>   The B option.
      -abool     The A bool
      -bbool     The B bool
      --help     Show help options.
      --version  Print program version.
----
myscript 0.0.0
Copyright (C)20.. Your Name
License...
)"

if $a ; then
    echo "a option! with $a"
fi

if $b ; then
    echo "b option! with $b"
fi

if $abool ; then 
    echo "abool option!"
fi


if $bbool ; then 
    echo "bbool option!"
fi

#3


0  

This is not quite perfect because it will always process the first switch, but it does place an exit inside the while loop which is in keeping with your design requirement. It may give you an idea how to finish it.

这不是很完美,因为它总是处理第一个开关,但它确实在while循环中放置了一个符合您的设计要求的出口。它可能会让你知道如何完成它。

#!/bin/bash

usage()
{
  echo -e "need help!"
}

while getopts "a:b:h" OPTION
do
     case $OPTION in
     a)
       aflag=1
       aval=$OPTARG
       if [ ! -z "$bflag" ]
       then
         printf "ERROR: cant use both -a and -b\n"
         exit 1
       fi
       ;;
    b)
       bflag=1
       bval=$OPTARG
       if [ ! -z "$aflag" ]
       then
        printf "ERROR: cant use both -a and -b\n"
        exit 1
       fi
       ;;
    h) usage ;;
    ?) printf "ERROR" ; exit 1 ;;
   esac
done

if [ ! -z "$aflag" ]
then    
  printf "a option with value %s $aval\n"
elif [ ! -z "$bflag" ]
then
  printf "b option with value %s $bval\n"
fi

exit 0

#1


1  

you've almost got it. The : after the a and after the b say that they take an argument, so your example with -a -b is actually valid, saying "There is option a with value -b".

你几乎得到了它。 :a之后和之后b表示他们接受了一个参数,所以你的例子-a -b实际上是有效的,说“有选项a带值-b”。

If you really just want "-a or -b and then an argument", you probably don't need getopts at all, but should do:

如果你真的只想要“-a或-b然后一个参数”,你可能根本不需要getopts,但是应该这样做:

[ "$1" == "-a" ] && printf "a option with value %s\n" $2
[ "$1" == "-b" ] && printf "b option with value %s\n" $2

#2


0  

any one have batter idea how to use getopts for this type validation?

任何人都有击球手的想法如何使用getopts进行此类型验证?

well, actually, you're explicitly telling geptopts that -a and -b are not boolean parameters, but parameters that take an extra argument. The argument parser cannot tell whether the argument following -a is a parameter or its own argument, and thus they consider [-a ] [-b ] as syntax.

好吧,实际上,你明确告诉geptopts -a和-b不是布尔参数,而是需要额​​外参数的参数。参数解析器无法判断-a后面的参数是参数还是自己的参数,因此他们将[-a] [-b]视为语法。

The best way, would actually be to have a different boolean parameter that matches the use case when you do not want an argument for -a and -b.

最好的方法,实际上是当你不想要-a和-b的参数时,有一个不同的布尔参数匹配用例。

Though, it won't help you with your issue trying to have parameters with argument or boolean, but for the argument syntax checking you can try docopt which has a nicer way to create command line interface. You focus on doing the --help documentation, it parses it to build your parameter/argument parser. e.g.:

虽然,它不会帮助您尝试使用参数或布尔值的参数,但对于参数语法检查,您可以尝试docopt,它有一个更好的方法来创建命令行界面。您专注于执行--help文档,它会解析它以构建您的参数/参数解析器。例如。:

eval "$(docopts -V - -h - : "$@" <<EOF
Usage: myscript [(-a <foo> | -b <bar> | -abool | -bbool)]

      -a <foo>   The A option.
      -b <bar>   The B option.
      -abool     The A bool
      -bbool     The B bool
      --help     Show help options.
      --version  Print program version.
----
myscript 0.0.0
Copyright (C)20.. Your Name
License...
)"

if $a ; then
    echo "a option! with $a"
fi

if $b ; then
    echo "b option! with $b"
fi

if $abool ; then 
    echo "abool option!"
fi


if $bbool ; then 
    echo "bbool option!"
fi

#3


0  

This is not quite perfect because it will always process the first switch, but it does place an exit inside the while loop which is in keeping with your design requirement. It may give you an idea how to finish it.

这不是很完美,因为它总是处理第一个开关,但它确实在while循环中放置了一个符合您的设计要求的出口。它可能会让你知道如何完成它。

#!/bin/bash

usage()
{
  echo -e "need help!"
}

while getopts "a:b:h" OPTION
do
     case $OPTION in
     a)
       aflag=1
       aval=$OPTARG
       if [ ! -z "$bflag" ]
       then
         printf "ERROR: cant use both -a and -b\n"
         exit 1
       fi
       ;;
    b)
       bflag=1
       bval=$OPTARG
       if [ ! -z "$aflag" ]
       then
        printf "ERROR: cant use both -a and -b\n"
        exit 1
       fi
       ;;
    h) usage ;;
    ?) printf "ERROR" ; exit 1 ;;
   esac
done

if [ ! -z "$aflag" ]
then    
  printf "a option with value %s $aval\n"
elif [ ! -z "$bflag" ]
then
  printf "b option with value %s $bval\n"
fi

exit 0