简体   繁体   English

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

[英]Mass arguments (operands) at first place in command line argument passing

I use following lines (hope this is best practice if not correct me please) to handle command line options: 我使用以下行(希望这是最好的做法,如果不能纠正我)来处理命令行选项:

#!/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"

If I call the script way that mass arguments (those that are not switches or arguments for switches) are last arguments everything is working correctly: 如果我调用脚本的方式, 质量参数 (那些不是开关的开关或参数)是最后一个参数,一切都正常工作:

$ ./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

The problem is when I want to call the script so the mass arguments are first (or somewhere in the middle of switches that do not use arguments) 问题是,当我想调用脚本时,质量参数是第一个(或者在不使用参数的开关中间的某个地方)

$ ./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

or 要么

$ ./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

I think this should be OK according (POSIX) standards, because following syntax which is basically the same is working as expected on my system: 我认为这应该是(POSIX)标准,因为基本相同的语法在我的系统上按预期工作:

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

I have search over the Internet but only thing that was close to my problem was this one related to C. 我有搜索在互联网上,但只有一件事情是接近我的问题是这样一个关系到C.

getopts automatically breaks the while loop as soon as it detects a non-dash parameter (not including the argument given to dash parameters that take arguments). 一旦检测到非破折号参数(不包括给参数的破折号参数赋予的参数), getopts自动打破while循环。 The POSIX standard is to have dashed parameters come first, and then have files . POSIX标准是首先使用虚线参数,然后是文件 There's also none of this -- and + crap either. 也没有这个--+废话。 It's plain and simple. 它简单明了。

However, Linux isn't Unix or POSIX compliant. 但是,Linux不符合Unix或POSIX标准。 It's just in the nature of the GNU utilities to be " better " than the standard Unix utilities. 与标准的Unix实用程序相比,GNU实用程序的本质就是“ 更好 ”。 More features, more options, and handling things a bit differently. 更多功能,更多选项和处理方式略有不同。

On Linux, command line parameters can come after files in many GNU utilities. 在Linux上,命令行参数可以在许多GNU实用程序中的文件之后

For example: 例如:

$ cp -R foo bar

Work on my Unix certified Mac OS X and on Linux, However, 在我的Unix认证的Mac OS X和Linux上工作,但是,

$ cp foo bar -R

Only works on Linux. 仅适用于Linux。

If you want getopts to work like a lot of Linux utilities, you need to do a wee bit of work. 如果你想让getopts像许多Linux工具一样工作,你需要做一些工作。

First, you have to process your arguments yourself, and not depend upon $OPTIND to parse them. 首先,您必须自己处理您的参数,而不是依赖$OPTIND来解析它们。 You also need to verify that you have an argument. 您还需要验证您是否有参数。

I came up with this as an example of doing what you want. 我想出了这个做你想要的事情的例子。

#! /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"

I now loop as long as $* is set. 我现在循环只要$*设置。 (Maybe I should use $@ ?) I have to do a shift at the end of the loop. (也许我应该使用$@ ?)我必须在循环结束时进行shift I also reset $OPTIND to 1 each time because I'm shifting the arguments off myself. 我也每次将$OPTIND重置$OPTIND 1因为我正在自行改变参数。 $OPTARG is still set, but I have to do another shift to make sure everything works. $OPTARG仍然设置,但我必须做另一个shift ,以确保一切正常。

I also have to verify if a argument begins with a dash or not using a regular expression in my if statement. 我还必须在if语句中使用正则表达式验证参数是否以破折号开头。

Basic testing shows it works, but I can't say it's error free, but it does give you an idea how you have to handle your program. 基本测试显示它有效,但我不能说它没有错误,但它确实让你知道如何处理你的程序。

There's still plenty of power you're getting from getopts , but it does take a bit more work. 你仍然可以从getopts获得足够的力量,但它确实需要更多的工作。

Bash provides two methods for argument parsing. Bash提供了两种参数解析方法。

The built-in command getopts is a newer, easy to use mechanism how to parse arguments but it is not very flexible. 内置命令getopts是一个更新,易于使用的机制,如何解析参数,但它不是很灵活。 getopts does not allow to mix options and mass arguments. getopts不允许混合选项和质量参数。

The external command getopt is an older and more complex mechanism to parse arguments. 外部命令getopt是一种较旧且更复杂的解析参数的机制。 It allows long/short options and the gnu extension allow to mix options and mass arguments. 它允许长/短选项,gnu扩展允许混合选项和质量参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM