[英]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.