我想这样调用myscript文件:
$ ./myscript -s 45 -p any_string
or
$ ./myscript -h #should display help
$ ./myscript #should display help
我的要求是:
Getopt在这里获取输入参数
检查-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
但是使用这些代码,我会得到错误。怎么和巴斯一起去?
原始代码的问题是:
H:在不应该的地方期望参数,因此将其更改为H(不带冒号)
要使用-p any_string,需要将p:添加到参数列表中
基本上:在选项后面意味着它需要参数。
getopts的基本语法是(参见:man bash):
getopts OPTSTRING VARNAME [ARGS...]
地点:
OPTSTRING is string with list of expected arguments,
h - check for option -h without parameters; gives error on unsupported options;
h: - check for option -h with parameter; gives errors on unsupported options;
abc - check for options -a, -b, -c; gives errors on unsupported options;
:abc - check for options -a, -b, -c; silences errors on unsupported options;
Notes: In other words, colon in front of options allows you handle the errors in your code. Variable will contain ? in the case of unsupported option, : in the case of missing value.
OPTARG - is set to current argument value,
OPTERR - indicates if Bash should display error messages.
所以代码可以是:
#!/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教程
在马克·G。的评论(在Adrian Frühwirth的答案下)变成了一个更可读的答案-这展示了如何避免使用getopts来获得可选参数:
usage() {
printf "Usage: %s <req> [<-s|--sopt> <45|90>] [<-p|--popt> <string>]\n" "$0";
return 1;
};
main() {
req="${1:?$(usage)}";
shift;
s="";
p="";
while [ "$#" -ge 1 ]; do
case "$1" in
-s|--sopt)
shift;
s="${1:?$(usage)}";
[ "$s" -eq 45 ] || [ "$s" -eq 90 ] || {
usage;
return 1;
}
;;
-p|--popt)
shift;
p="${1:?$(usage)}"
;;
*)
usage;
return 1
;;
esac;
shift;
done;
printf "req = %s\ns = %s\np = %s\n" "$req" "$s" "$p";
};
main "$@"
正如n.caillou的评论所指出的:
如果选项和参数之间没有空格,它就会失败。
然而,为了使它更符合POSIX(来自Mark G。的其他评论):
case "$1" in
-s*)
s=${1#-s};
if [ -z "$s" ];
shift;
s=$1;
fi
POSIX 7示例
同样值得检查标准中的示例: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是dash 0.5.8。
原始代码的问题是:
H:在不应该的地方期望参数,因此将其更改为H(不带冒号)
要使用-p any_string,需要将p:添加到参数列表中
基本上:在选项后面意味着它需要参数。
getopts的基本语法是(参见:man bash):
getopts OPTSTRING VARNAME [ARGS...]
地点:
OPTSTRING is string with list of expected arguments,
h - check for option -h without parameters; gives error on unsupported options;
h: - check for option -h with parameter; gives errors on unsupported options;
abc - check for options -a, -b, -c; gives errors on unsupported options;
:abc - check for options -a, -b, -c; silences errors on unsupported options;
Notes: In other words, colon in front of options allows you handle the errors in your code. Variable will contain ? in the case of unsupported option, : in the case of missing value.
OPTARG - is set to current argument value,
OPTERR - indicates if Bash should display error messages.
所以代码可以是:
#!/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教程
Getopts和getopt非常有限。虽然建议完全不要使用getopt,但它确实提供了长选项。而getopts只允许单字符选项,如-a -b。使用这两种方法都有一些缺点。
所以我写了一个小脚本来替换getopts和getopt。
这是一个开始,它可能会有很大的改进。
更新08-04-2020:我已经添加了对连字符的支持,例如——package-name。
使用方法:"./script.sh package install——package "name with space"
——建立档案”
# Example:
# parseArguments "${@}"
# echo "${ARG_0}" -> package
# echo "${ARG_1}" -> install
# echo "${ARG_PACKAGE}" -> "name with space"
# echo "${ARG_BUILD}" -> 1 (true)
# echo "${ARG_ARCHIVE}" -> 1 (true)
function parseArguments() {
PREVIOUS_ITEM=''
COUNT=0
for CURRENT_ITEM in "${@}"
do
if [[ ${CURRENT_ITEM} == "--"* ]]; then
printf -v "ARG_$(formatArgument "${CURRENT_ITEM}")" "%s" "1" # could set this to empty string and check with [ -z "${ARG_ITEM-x}" ] if it's set, but empty.
else
if [[ $PREVIOUS_ITEM == "--"* ]]; then
printf -v "ARG_$(formatArgument "${PREVIOUS_ITEM}")" "%s" "${CURRENT_ITEM}"
else
printf -v "ARG_${COUNT}" "%s" "${CURRENT_ITEM}"
fi
fi
PREVIOUS_ITEM="${CURRENT_ITEM}"
(( COUNT++ ))
done
}
# Format argument.
function formatArgument() {
ARGUMENT="${1^^}" # Capitalize.
ARGUMENT="${ARGUMENT/--/}" # Remove "--".
ARGUMENT="${ARGUMENT//-/_}" # Replace "-" with "_".
echo "${ARGUMENT}"
}