BASH getopts 可选参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17016007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:38:34  来源:igfitidea点击:

BASH getopts optional arguments

linuxbashshellunixgetopts

提问by Villi Magg

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. The user types in terminal f.ex.:

这是一个安装脚本,它利用 GIT 从 Github 存储库中获取应用程序。用户在终端 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, e.g. develop branch. Meaning that the user could do:

并且脚本从这个存储库中获取 master 分支的一个实例。然而,如果用户选择使用可选的 -b 标志,这意味着他/她想要指定要获取的分支,例如开发分支。这意味着用户可以执行以下操作:

./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. But that is perhaps not the most important thing at the moment.

我也很好奇你如何让脚本工作,这样用户在'new'参数和'app_name'参数之前输入 -b flag+branch_name 就无关紧要。但这可能不是目前最重要的事情。

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

P.S.: 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. Thus am I here asking y'all great people for help.

PS:我一直在尝试使用 getopts 的许多示例,我在 Stackoverflow 和其他博客上都找到了这些示例,但没有一个能帮助我完全使其工作。因此,我在这里向你们所有伟大的人寻求帮助。

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

问候, 维利

回答by cforbish

I normally write my own to allow for short and long options:

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

function Usage()
{
cat <<-ENDOFMESSAGE

# "shift" version: always shift consumed arguments
local verb="" branch=master app_name option
shift
case $verb in
  new)  app_name=""
        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))
[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= shift case ${opt} in -b|--branch) if [ $# -eq 0 -o "${1:0:1}" = "-" ]; then Die "The ${opt} option requires an argument." fi branch="" 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[@]}"

回答by rici

Unix utilities normally take optional arguments ("flags") beforethe 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. However, the bash builtin getoptsdoes not shuffle, which means that it is up to you to do so if you want to.

Unix 实用程序通常在位置参数之前采用可选参数(“标志”),尽管大多数 GNU 实用程序,包括 C 库函数的 GNU 实现getopt,会随机播放命令行参数,以便可选参数排在最前面。但是,内置的 bashgetopts不会随机播放,这意味着如果您愿意,可以由您自行决定。

getoptsalways starts with the argument whose number is the value of the variable 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 getoptswill start with that index. Alternatively, you can use shiftto shift all the command line arguments over.

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

So, for example, you could do this:

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

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

Or:

或者:

#!/usr/bin/bash

help() { echo -e "Usage\n\t
$./test new App
app_name: App, develop:
$./test new App -b Dev
app_name: App, develop: Dev
: new <app_name> [-b <develop>]" >&2;} die() { [ -n "" ] && echo -e "Error: \n" >&2; help; [ -z "" ]; exit;} [ $# -lt 2 ] && die "Too few args" [ != "new" ] && die "Bad first arg ()" app_name= 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"

回答by TrueY

A little bit simplified version, using that getoptscan report errors:

稍微简化的版本,使用它getopts会报错:

##代码##

Test:

测试:

##代码##

Anyway I may suggest to use to use the standard way of argument passing. Instead of newyou may use -n.

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