在命令行参数传递的第一个位置的质量参数(操作数)

时间:2015-02-18 12:17:07

标签: bash parameter-passing command-line-arguments getopts

我使用以下行(希望这是最好的做法,如果不能纠正我)来处理命令行选项:

#!/usr/bin/bash

read -r -d '' HELP <<EOF
OPTIONS:
-c    Enable color output
-d    Enable debug output
-v    Enable verbose output
-n    Only download files (mutually exclusive with -r)
-r    Only remove files (mutually exclusive with -n)
-h    Display this help
EOF

# DECLARE VARIABLES WITH DEFAULT VALUES
color=0
debug=0
verbose=0
download=0
remove=0


OPTIND=1                # Reset in case getopts has been used previously in the shell
invalid_options=();     # Array for invalid options

while getopts ":cdvnrh" opt; do
  echo "Actual opt: $opt"
  case $opt in
    c)
      color=1
      ;;
    d)
      debug=1
      ;;
    v)
      verbose=1
      ;;
    n)
      download=1
      ;;
    r)
      remove=1
      ;;
    h)
      echo "$HELP"
      exit 1
      ;;
   \?)
      invalid_options+=($OPTARG)
      ;;
   *)
      invalid_options+=($OPTARG)
      ;;
  esac
done

# HANDLE INVALID OPTIONS
if [ ${#invalid_options[@]} -ne 0 ]; then
  echo "Invalid option(s):" >&2
  for i in "${invalid_options[@]}"; do
    echo $i >&2
  done
  echo "" >&2
  echo "$HELP" >&2
  exit 1
fi

# SET $1 TO FIRST MASS ARGUMENT, $2 TO SECOND MASS ARGUMENT ETC
shift $((OPTIND - 1))

# HANDLE CORRECT NUMBER OF MASS OPTIONS
if [ $# -ne 2 ]; then
  echo "Correct number of mass arguments are 2"
  echo "" >&2
  echo "$HELP" >&2
  exit 1
fi


# HANDLE MUTUALLY EXCLUSIVE OPTIONS
if [ $download -eq 1 ] && [ $remove -eq 1 ]; then
  echo "Options for download and remove are mutually exclusive" >&2
  echo "$HELP" >&2
  exit 1
fi



echo "color:    $color"
echo "debug:    $debug"
echo "verbose:  $verbose"
echo "download: $download"
echo "remove:   $remove"
echo "\$1:      $1"
echo "\$2:      $2"

如果我调用脚本方式mass arguments(那些不是开关的开关或参数)是最后一个参数,一切都正常工作:

$ ./getopts.sh -c -d -v -r a b
Actual opt: c
Actual opt: d
Actual opt: v
Actual opt: r
color:    1
debug:    1
verbose:  1
download: 0
remove:   1
$1:      a
$2:      b

问题是当我想调用脚本时所以质量参数是第一个(或者在不使用参数的开关中间的某个地方)

$ ./getopts.sh a b -c -d -v -r
Correct number of mass arguments are 2

OPTIONS:
-c    Enable color output
-d    Enable debug output
-v    Enable verbose output
-n    Only download files (mutually exclusive with -r)
-r    Only remove files (mutually exclusive with -d)
-h    Display this help

$ ./getopts.sh -c a b -d -v -r
Actual opt: c
Correct number of mass arguments are 2

OPTIONS:
-c    Enable color output
-d    Enable debug output
-v    Enable verbose output
-n    Only download files (mutually exclusive with -r)
-r    Only remove files (mutually exclusive with -d)
-h    Display this help

我认为根据(POSIX)标准这应该没问题,因为基本相同的语法在我的系统上按预期工作:

$ cp test1/ test2/ -r
$ cp test1/ -r test2/

我在互联网上搜索,但只有与我的问题接近的是与{C}相关的this one

2 个答案:

答案 0 :(得分:3)

getopts一旦检测到非破折号参数(不包括赋予参数的破折号参数的参数),就会自动中断while循环。 POSIX标准是首先使用虚线参数,然后使用文件。也没有这个--+废话。这很简单。

但是,Linux不符合Unix或POSIX标准。与标准的Unix实用程序相比,GNU实用程序的本质就是“更好”。更多功能,更多选项和处理方式略有不同。

在Linux上,命令行参数可以在许多GNU实用程序中的文件之后

例如:

$ cp -R foo bar

在我的Unix认证的Mac OS X和Linux上工作,但是,

$ cp foo bar -R

仅适用于Linux。

如果您希望getopts像许多Linux实用程序一样工作,那么您需要做一些工作。

首先,您必须自己处理您的参数,而不是依靠$OPTIND来解析它们。您还需要验证您是否有参数。

我想出了这个做你想做的事的例子。

#! /bin/bash

while [[ $* ]]
do
    OPTIND=1
    echo $1
    if [[ $1 =~ ^- ]]
    then
        getopts :a:b:cd parameter
        case $parameter in
            a)  echo "a"
                echo "the value is $OPTARG"
                shift
                ;;
            b)  echo "b"
                echo "the value is $OPTARG"
                shift
                ;;
            c)  echo "c"
                ;;
            d)  echo "d"
                ;;
            *) echo "This is an invalid argument: $parameter"
                ;;
        esac
    else
        other_arguments="$other_arguments $1"
    fi
    shift
done
echo "$other_arguments"

只要设置$*,我现在就循环播放。 (也许我应该使用$@?)我必须在循环结束时执行shift。我每次都将$OPTIND重置为1,因为我正在自行改变论点。 $OPTARG仍然设置,但我必须做另一个shift以确保一切正常。

我还必须在我的if声明中使用正则表达式验证参数是否以破折号开头。

基本测试显示它有效,但我不能说它没有错误,但它确实让你知道如何处理你的程序。

你仍然可以从getopts获得足够的力量,但它确实需要更多的工作。

答案 1 :(得分:1)

Bash提供了两种参数解析方法。

内置命令getopts是一种更新,易于使用的机制,如何解析参数,但它不是很灵活。 getopts不允许混合选项和大量参数。

外部命令getopt是一种较旧且更复杂的解析参数的机制。它允许长/短选项,gnu扩展允许混合选项和质量参数。