linux - long - shellscript getopts




一個如何在bash中使用getopts的例子 (4)

POSIX 7例子

檢查標準中的例子也是值得的: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html : http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html

aflag=
bflag=
while getopts ab: name
do
    case $name in
    a)    aflag=1;;
    b)    bflag=1
          bval="$OPTARG";;
    ?)   printf "Usage: %s: [-a] [-b value] args\n" $0
          exit 2;;
    esac
done
if [ ! -z "$aflag" ]; then
    printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
    printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"

然後我們可以嘗試一下:

$ sh a.sh
Remaining arguments are: 
$ sh a.sh -a
Option -a specified
Remaining arguments are: 
$ sh a.sh -b
No arg for -b option
Usage: a.sh: [-a] [-b value] args
$ sh a.sh -b myval
Option -b "myval" specified
Remaining arguments are: 
$ sh a.sh -a -b myval
Option -a specified
Option -b "myval" specified
Remaining arguments are: 
$ sh a.sh remain
Remaining arguments are: remain
$ sh a.sh -- -a remain
Remaining arguments are: -a remain

測試在Ubuntu 17.10中, sh是破折號0.5.8。

我想以這種方式調用myscript文件:

$ ./myscript -s 45 -p any_string

要么

$ ./myscript -h >>> should display help
$ ./myscript    >>> should display help

我的要求是:

  • 在這裡獲取輸入參數
  • 檢查-s存在,如果沒有返回錯誤
  • 檢查-s之後的值是45還是90
  • 檢查-p存在,之後是否有輸入字符串
  • 如果用戶輸入./myscript -h或只./myscript則顯示幫助

我試過迄今為止的這段代碼:

#!/bin/bash
while getopts "h:s:" arg; do
  case $arg in
    h)
      echo "usage" 
      ;;
    s)
      strength=$OPTARG
      echo $strength
      ;;
  esac
done

但有了這個代碼,我得到錯誤。 如何用Bash和getopt做到這一點?


原始代碼的問題是:

  • h:期望參數不應該在那裡,所以把它改成h (不用冒號)
  • 期望-p any_string ,您需要將p:添加到參數列表

getopts的基本語法是(參見: man bash ):

getopts OPTSTRING VARNAME [ARGS...]

哪裡:

  • OPTSTRING是帶有預期參數列表的字符串,

    • h - 檢查沒有參數的選項-h ; 在不支持的選項上出錯;
    • h: - 參數檢查選項-h ; 在不支持的選項上出錯;
    • abc - 檢查選項-a-b-c ; 在不支持的選項上出錯;
    • :abc - 檢查選項-a-b-c ; 消除不支持的選項上的錯誤;

      注意:換句話說,選項前面的冒號允許您處理代碼中的錯誤。 變量將包含? 在不支持選項的情況下:在缺失值的情況下。

  • OPTARG - 被設置為當前參數值,

  • OPTERR - 指示Bash是否應顯示錯誤消息。

所以代碼可以是:

#!/usr/bin/env bash
usage() { echo "$0 usage:" && grep " .)\ #" $0; exit 0; }
[ $# -eq 0 ] && usage
while getopts ":hs:p:" arg; do
  case $arg in
    p) # Specify p value.
      echo "p is ${OPTARG}"
      ;;
    s) # Specify strength, either 45 or 90.
      strength=${OPTARG}
      [ $strength -eq 45 -o $strength -eq 90 ] \
        && echo "Strength is $strength." \
        || echo "Strength needs to be either 45 or 90, $strength found instead."
      ;;
    h | *) # Display help.
      usage
      exit 0
      ;;
  esac
done

用法示例:

$ ./foo.sh 
./foo.sh usage:
    p) # Specify p value.
    s) # Specify strength, either 45 or 90.
    h | *) # Display help.
$ ./foo.sh -s 123 -p any_string
Strength needs to be either 45 or 90, 123 found instead.
p is any_string
$ ./foo.sh -s 90 -p any_string
Strength is 90.
p is any_string

請參閱:Bash Hackers Wiki上的小型getopts教程


getopt打包的例子(我的發行版放在/usr/share/getopt/getopt-parse.bash )看起來像涵蓋了所有的情況:

#!/bin/bash

# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh

# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'

# Note that we use `"[email protected]"' to let each command-line parameter expand to a 
# separate word. The quotes around `[email protected]' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n 'example.bash' -- "[email protected]"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -a|--a-long) echo "Option a" ; shift ;;
        -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
        -c|--c-long) 
            # c has an optional argument. As we are in quoted mode,
            # an empty parameter will be generated if its optional
            # argument is not found.
            case "$2" in
                "") echo "Option c, no argument"; shift 2 ;;
                *)  echo "Option c, argument \`$2'" ; shift 2 ;;
            esac ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done

#!/bin/bash

usage() { echo "Usage: $0 [-s <45|90>] [-p <string>]" 1>&2; exit 1; }

while getopts ":s:p:" o; do
    case "${o}" in
        s)
            s=${OPTARG}
            ((s == 45 || s == 90)) || usage
            ;;
        p)
            p=${OPTARG}
            ;;
        *)
            usage
            ;;
    esac
done
shift $((OPTIND-1))

if [ -z "${s}" ] || [ -z "${p}" ]; then
    usage
fi

echo "s = ${s}"
echo "p = ${p}"

示例運行:

$ ./myscript.sh
Usage: ./myscript.sh [-s <45|90>] [-p <string>]

$ ./myscript.sh -h
Usage: ./myscript.sh [-s <45|90>] [-p <string>]

$ ./myscript.sh -s "" -p ""
Usage: ./myscript.sh [-s <45|90>] [-p <string>]

$ ./myscript.sh -s 10 -p foo
Usage: ./myscript.sh [-s <45|90>] [-p <string>]

$ ./myscript.sh -s 45 -p foo
s = 45
p = foo

$ ./myscript.sh -s 90 -p bar
s = 90
p = bar




getopts