BASH getopts可选参数

时间:2013-06-10 02:02:52

标签: linux bash shell unix getopts

我试图创建一个shell脚本,它有两个必需参数(arg1,arg2),然后是一个可选的-b标志加上用户选择使用该标志时需要遵循的参数。

让我解释一下:

它是一个安装脚本,它利用GIT从Github存储库中获取应用程序。用户键入终端f.ex。:

./shellscript.sh new <app_name> # fetches master branch by default

,脚本从此存储库中获取主分支的实例。然而,用户是否应该选择使用可选的-b标志,这意味着他/她想要指定要获取的分支,例如发展分支。意味着用户可以这样做:

./shellscript.sh new <app_name> -b develop # or which ever branch there is available

我也很好奇你如何才能使脚本正常工作,以便用户在新的&#39;之前键入-b标志+ branch_name并不重要。参数和&#39; app_name&#39;论点。但这可能不是目前最重要的事情。

要了解我正在尝试构建的内容,这里是指向我当前脚本的链接,该脚本仅接受两个必需参数并仅获取主分支:My Super Cool Artisan Executable Script

P.S。:我一直在尝试使用getopts的许多例子,我在Stackoverflow和其他博客上都找到了这些例子,但没有一个帮助我完全使用它。因此,我在这里向所有伟大的人寻求帮助。

非常感谢,请务必查看我的Linux Mint / Ubuntu - Post Install Script for only cool people(you guys and those switching over to Linux from Windows/Mac)

此致 绒毛

3 个答案:

答案 0 :(得分:5)

我通常会自己编写以允许短期和长期选择:

function Usage()
{
cat <<-ENDOFMESSAGE

$0 [OPTION] REQ1 REQ2

options:

    -b -branch  branch to use
    -h --help   display this message

ENDOFMESSAGE
    exit 1
}

function Die()
{
    echo "$*"
    exit 1
}

function GetOpts() {
    branch=""
    argv=()
    while [ $# -gt 0 ]
    do
        opt=$1
        shift
        case ${opt} in
            -b|--branch)
                if [ $# -eq 0 -o "${1:0:1}" = "-" ]; then
                    Die "The ${opt} option requires an argument."
                fi
                branch="$1"
                shift
                ;;
            -h|--help)
                Usage;;
            *)
                if [ "${opt:0:1}" = "-" ]; then
                    Die "${opt}: unknown option."
                fi
                argv+=(${opt});;
        esac
    done 
}

GetOpts $*
echo "branch ${branch}"
echo "argv ${argv[@]}"

答案 1 :(得分:2)

Unix实用程序通常在位置参数之前使用可选参数(“flags”),尽管大多数GNU实用程序,包括C库函数getopt的GNU实现,随机命令行参数所以可选参数首先出现。但是,bash builtin getopts不会随机播放,这意味着如果你愿意,你可以这样做。

getopts始终以参数开头,参数的编号是变量OPTIND的值。 (每次执行bash函数时OPTIND都设置为1,并且它是一个全局变量。因此需要相互调用的bash函数需要注意。)如果你愿意,你可以自己设置OPTIND,然后下一个对getopts的调用将从该索引开始。或者,您可以使用shift来移动所有命令行参数。

因此,例如,你可以这样做:

# "shift" version: always shift consumed arguments
local verb="$1" branch=master app_name option
shift
case $verb in
  new)  app_name="$1"
        shift
        while getopts b: option; do
          case $option in
            b) branch=$OPTARG;;
            *) # handle the error;;
          esac
        done
        shift $((OPTIND - 1));;
  *) # handle the error or other subcommands;;
esac
# At this point, there are still arguments if ((OPTIND > 0))

或者:

# non-shift version: use OPTIND to index arguments
local verb="${!OPTIND}" branch=master app_name option
OPTIND=$((OPTIND + 1))
case $verb in
  new)  app_name="${!OPTIND}"
        OPTIND=$((OPTIND + 1))
        while getopts b: option; do
          case $option in
            b) branch=$OPTARG;;
            *) # handle the error;;
          esac
        done;;
  *) # handle the error or other subcommands;;
esac
# At this point, there are still arguments if ((OPTIND > $#))

答案 2 :(得分:1)

稍微简化的版本,使用getopts可以报告错误:

#!/usr/bin/bash

help() { echo -e "Usage\n\t$0: new <app_name> [-b <develop>]" >&2;}
die() { [ -n "$1" ] && echo -e "Error: $1\n" >&2; help; [ -z "$1" ]; exit;}

[ $# -lt 2 ] && die "Too few args"
[ $1 != "new" ] && die "Bad first arg ($1)"
app_name=$2
shift 2

unset develop
while getopts "b:" opt; do
  case $opt in
    \?) exit 1;;
    b) develop="$OPTARG";;
  esac
done

echo "app_name: $app_name, develop: $develop"

测试:

$./test new App
app_name: App, develop:
$./test new App -b Dev
app_name: App, develop: Dev

无论如何,我可能会建议使用标准的参数传递方式。您可以使用new代替-n