简体   繁体   English

BASH getopts可选参数

[英]BASH getopts optional arguments

I'm trying to create a shell script that has two mandatory arguments (arg1, arg2) and then an optional -b flag plus the argument that needs to follow should the user choose to use the flag. 我正在尝试创建一个shell脚本,它有两个必需参数(arg1,arg2),然后是一个可选的-b标志加上用户选择使用该标志时需要遵循的参数。

Let me explain: 让我解释:

It's an install script that takes an advantage of GIT to fetch an application from a Github repository. 这是一个安装脚本,它利用GIT从Github存储库中获取应用程序。 The user types in terminal f.ex.: 用户键入终端f.ex。:

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

and the script fetches an instance of the master branch from this repository. 并且脚本从此存储库中获取主分支的实例。 Should the user however choose to use the optional -b flag that would mean that he/she wants to specify which branch to fetch, eg develop branch. 但是,用户是否应该选择使用可选的-b标志,这意味着他/她想要指定要获取的分支,例如开发分支。 Meaning that the user could do: 意味着用户可以这样做:

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

I'm also curious how you could go about making the script work so that it wouldn't matter if the user types in the -b flag+branch_name before the 'new' argument and the 'app_name' argument. 我也很好奇如何使脚本工作,以便用户在'new'参数和'app_name'参数之前键入-b标志+ branch_name并不重要。 But that is perhaps not the most important thing at the moment. 但这可能不是目前最重要的事情。

To know what exactly I'm trying to build, here is a link to my current script that only takes the two mandatory arguments and only fetches the master branch: My Super Cool Artisan Executable Script 要知道我正在尝试构建什么,这里是一个指向我当前脚本的链接,它只接受两个必需参数并且只获取主分支: My Super Cool Artisan Executable Script

PS: I've been trying out many examples using getopts which I've found both here on Stackoverflow and other blogs out there but none have helped me to completely make it work. PS:我一直在尝试使用getopts的很多例子,我在Stackoverflow和其他博客上都找到了这些例子,但是没有一个帮助我完全使它工作。 Thus am I here asking y'all great people for help. 因此,我在这里向你们所有人寻求帮助。

Huge thanks and be sure to check out my Linux Mint / Ubuntu - Post Install Script for only cool people(you guys and those switching over to Linux from Windows/Mac) 非常感谢,请务必查看我的Linux Mint / Ubuntu - 仅适用于酷人的安装后脚本(您和那些从Windows / Mac切换到Linux的人)

Regards, Villi 此致,Villi

I normally write my own to allow for short and long options: 我通常会自己编写以允许短期和长期期权:

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[@]}"

Unix utilities normally take optional arguments ("flags") before the positional arguments, although most GNU utilities, including the GNU implementation of the C library function getopt , shuffle command line arguments so that the optional arguments come first. Unix实用程序通常在位置参数之前使用可选参数(“flags”),尽管大多数GNU实用程序(包括C库函数getopt的GNU实现)都会getopt命令行参数,以便首先使用可选参数。 However, the bash builtin getopts does not shuffle, which means that it is up to you to do so if you want to. 但是,bash内置的getopts不会随机播放,这意味着如果你愿意,你可以这样做。

getopts always starts with the argument whose number is the value of the variable OPTIND . getopts始终以参数开头,参数的编号是变量OPTIND的值。 (OPTIND is set to 1 every time a bash function is executed, and it's a global variable. So a bit of caution is needed with bash functions which call each other.) If you want to, you can set OPTIND yourself, and the next call to getopts will start with that index. (每次执行bash函数时OPTIND都设置为1,并且它是一个全局变量。因此需要相互调用的bash函数需要注意。)如果你愿意,你可以自己设置OPTIND,然后下一个对getopts调用将从该索引开始。 Alternatively, you can use shift to shift all the command line arguments over. 或者,您可以使用shift来移动所有命令行参数。

So, for example, you could do this: 所以,例如,你可以这样做:

# "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))

Or: 要么:

# 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 > $#))

A little bit simplified version, using that getopts can report errors: 一点点简化版本,使用该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: 测试:

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

Anyway I may suggest to use to use the standard way of argument passing. 无论如何,我可能会建议使用标准的参数传递方式。 Instead of new you may use -n . 而不是new你可以使用-n

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

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