0

My shell script takes in a set of input variables some are optional. The input should follow the following signature.

myscript.sh var1 var2 [-x var3] [-y var4]`.

The -x and -y are optional inputs and these options can occur at any location (between var1 & var 2 or at the start) but var3 will always preceed var4. Also var1 will preceed var 2.

The script I have does a lot of if else checks to cover all the probabilities. Something like this

if [ $1 == "-x" ]; then
## Then check if $3 == "-y" 
## Assign values to VAR1 , VAR2, VAR3, VAR4 
## else check for other possibilities
fi

I was wondering if there was a better way of doing this and assigning the values to variables?

4

4 回答 4

3

看看getopts

man getopts

如果您想要较长的 GNU 样式开关,请参阅

getopts_long_example

getopts_long

以及推荐的文档:http: //mywiki.wooledge.org/BashFAQ/035

于 2012-10-25T14:39:01.887 回答
2

很简单,甚至不需要 getopt。请注意,以下使用 bash-only 语法,因此您应该以 开始脚本#!/bin/bash,而不是#!/bin/sh.

args=()
while (( $# )); do
  if [[ $1 = -x ]] ; then
    x_val=$2
    shift; shift
  elif [[ $1 = -y ]] ; then
    y_val=$2
    shift; shift
  elif (( ${#args[@]} < 2 )); then
    args+=( "$1" )
    shift
  else
    printf 'Unhandled argument: %q\n' "$1" >&2
    exit 1
  fi
done
if (( ${#args[@]} < 2 )) ; then
  echo "Needed at least 2 positional arguments; got only ${#args[@]}." >&2
  exit 1
fi

另请参阅相关的 BashFAQ 条目

于 2012-10-25T14:55:38.603 回答
1

通过测试确保可选参数(如果提供)仅提供一次。

#!/bin/bash

die() {
    echo >&2 $@
    exit 1
}

declare -a vars_1_2
var1='' var2='' var3='' var4=''
while [ "$1" ];do
    case $1 in
        -x ) [ "$var3" ] && die "Argument '-x' provided twice!"
             shift
             var3=$1
             shift
             ;;
        -y ) [ "$var4" ] && die "Argument '-y' provided twice!" 
             shift
             var4=$1
             shift
             ;;
        * ) vars_1_2+=($1) ; shift ;;
    esac
done
[ ${#vars_1_2[@]} -ne 2 ] && \
    die "Needed exactly 2 positional arguments. Got ${#vars_1_2[@]}."
var1=${vars_1_2[0]}
var2=${vars_1_2[1]}
set | grep ^var

制作:

$ ./parsargs.sh 12 33 -x 45 -y 67 -x 2
Argument '-x' provided twice!

$ ./parsargs.sh 12 -x 45 -y 67 
Needed exactly 2 positional arguments. Got 1.

$ ./parsargs.sh 12 34 -x 45 -y 67 
var1=12
var2=34
var3=45
var4=67
vars_1_2=([0]="12" [1]="34")
于 2012-10-25T18:36:38.687 回答
1

正如查尔斯所说:这项工作仅在 bash (>2 ;) 中起作用,这另一个目的似乎更紧凑:

#!/bin/bash

declare -a vars_1_2
var1='' var2='' var3='' var4=''
while [ "$1" ];do
    case $1 in
        -x ) shift ; var3=$1 ; shift ;;
        -y ) shift ; var4=$1 ; shift ;;
        * ) vars_1_2+=($1) ; shift ;;
    esac
done
if [ ${#vars_1_2[@]} -ne 2 ] ;then
    echo "Needed exactly 2 positional arguments. Got ${#vars_1_2[@]}." >&2
    exit 1
    fi
var1=${vars_1_2[0]}
var2=${vars_1_2[1]}
set | grep ^var

让我们探测一下这段代码:

$ ./parsargs.sh
Needed at least 2 positional arguments. Got 0.

$ ./parsargs.sh 12
Needed at least 2 positional arguments. Got 1.

$ ./parsargs.sh 12 34
var1=12
var2=34
var3=
var4=
vars_1_2=([0]="12" [1]="34")

$ ./parsargs.sh 12 34 56
Needed at least 2 positional arguments. Got 3.

$ ./parsargs.sh 12 34 -x 56
var1=12
var2=34
var3=56
var4=
vars_1_2=([0]="12" [1]="34")

$ ./parsargs.sh 12 34 -x 56 -y 78
var1=12
var2=34
var3=56
var4=78
vars_1_2=([0]="12" [1]="34")

$ ./parsargs.sh 12 34 -x 56 -y 78 -z 9
Needed at least 2 positional arguments. Got 4.

$ ./parsargs.sh -x 56 12 -y 78 34
var1=12
var2=34
var3=56
var4=78
vars_1_2=([0]="12" [1]="34")
于 2012-10-25T17:10:29.227 回答