我希望能够在我的脚本中接受强制和可选标志.这是我到目前为止所拥有的.
#!bin/bash
while getopts ":a:b:cdef" opt; do
case $opt in
a ) APPLE="$OPTARG";;
b ) BANANA="$OPTARG";;
c ) CHERRY="$OPTARG";;
d ) DFRUIT="$OPTARG";;
e ) EGGPLANT="$OPTARG";;
f ) FIG="$OPTARG";;
\?) echo "Invalid option: -"$OPTARG"" >&2
exit 1;;
: ) echo "Option -"$OPTARG" requires an argument." >&2
exit 1;;
esac
done
echo "Apple is "$APPLE""
echo "Banana is "$BANANA""
echo "Cherry is "$CHERRY""
echo "Dfruit is "$DFRUIT""
echo "Eggplant is "$EGGPLANT""
echo "Fig is "$FIG""
Run Code Online (Sandbox Code Playgroud)
但是,输出如下:
bash script.sh -a apple -b banana -c cherry -d dfruit -e eggplant -f fig
Run Code Online (Sandbox Code Playgroud)
...输出:
Apple is apple
Banana is banana
Cherry is
Dfruit is
Eggplant is
Fig is
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,可选标志不会像使用$ OPTARG那样使用所需的标志来提取参数.有没有办法在可选标志上读取$ OPTARG而不摆脱整齐的":)"错误处理?
编辑:我按照下面吉尔伯特的建议结束了.这是我做的:
#!/bin/bash
if [[ "$1" =~ ^((-{1,2})([Hh]$|[Hh][Ee][Ll][Pp])|)$ ]]; then
print_usage; exit 1
else
while [[ $# -gt 0 ]]; do
opt="$1"
shift;
current_arg="$1"
if [[ "$current_arg" =~ ^-{1,2}.* ]]; then
echo "WARNING: You may have left an argument blank. Double check your command."
fi
case "$opt" in
"-a"|"--apple" ) APPLE="$1"; shift;;
"-b"|"--banana" ) BANANA="$1"; shift;;
"-c"|"--cherry" ) CHERRY="$1"; shift;;
"-d"|"--dfruit" ) DFRUIT="$1"; shift;;
"-e"|"--eggplant" ) EGGPLANT="$1"; shift;;
"-f"|"--fig" ) FIG="$1"; shift;;
* ) echo "ERROR: Invalid option: \""$opt"\"" >&2
exit 1;;
esac
done
fi
if [[ "$APPLE" == "" || "$BANANA" == "" ]]; then
echo "ERROR: Options -a and -b require arguments." >&2
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
非常感谢大家.这到目前为止完美无缺.
nne*_*neo 42
:
意思是"接受论证",而不是"强制性论证".也就是说,未跟随的选项字符:
表示标志样式选项(无参数),而后跟的选项字符:
表示带参数的选项.
因此,你可能想要
getopts "a:b:c:d:e:f:" opt
Run Code Online (Sandbox Code Playgroud)
如果你想要"强制"选项(有点矛盾),你可以在参数解析后检查你的强制选项值是否都已设置.
小智 8
这并不容易......据getopts
我们所知,实际上必须要有任何"可选"选项参数.当然,可选参数必须是脚本的相同参数的一部分,而不是它所使用的选项.否则,-f
带有可选参数的选项-a
和带有必需参数的选项可能会混淆:
# Is -a an option or an argument?
./script.sh -f -a foo
# -a is definitely an argument
./script.sh -f-a foo
Run Code Online (Sandbox Code Playgroud)
执行此操作的唯一方法是测试选项及其参数是否与脚本位于同一参数中.如果是这样,OPTARG就是该选项的参数.否则,OPTIND必须减1.当然,该选项现在需要有一个参数,这意味着当一个选项缺少一个参数时会找到一个字符.只需使用另一个case
来确定是否需要任何选项:
while getopts ":a:b:c:d:e:f:" opt; do
case $opt in
a) APPLE="$OPTARG";;
b) BANANA="$OPTARG";;
c|d|e|f)
if test "$OPTARG" = "$(eval echo '$'$((OPTIND - 1)))"; then
OPTIND=$((OPTIND - 1))
else
case $opt in
c) CHERRY="$OPTARG";;
d) DFRUIT="$OPTARG";;
...
esac
fi ;;
\?) ... ;;
:)
case "$OPTARG" in
c|d|e|f) ;; # Ignore missing arguments
*) echo "option requires an argument -- $OPTARG" >&2 ;;
esac ;;
esac
done
Run Code Online (Sandbox Code Playgroud)
到目前为止,这对我有用.
bash
的getopts
该bash
手册页(报价4.1版手册)的getopts
说:
getopts optstring name
[args]
getopts
shell 脚本使用它来解析位置参数。optstring包含要识别的选项字符;如果一个字符后跟一个冒号,则该选项应该有一个参数,应该用空格将它与它分开。冒号 (':') 和问号 ('?') 不能用作选项字符。每次调用时,getopts
将下一个选项放在 shell 变量name 中,如果name不存在则初始化name,并将下一个要处理的参数的索引放入变量中OPTIND
。OPTIND
每次调用 shell 或 shell 脚本时都会初始化为 1。当一个选项需要一个参数时,getopts
将该参数放入变量中OPTARG
. 外壳不会OPTIND
自动重置;如果要使用getopts
一组新参数,则必须在同一个 shell 调用内的多次调用之间手动重置它。当遇到选项结束时,
getopts
以大于零的返回值退出。OPTIND
设置为第一个非选项参数的索引,名称设置为“?”。
getopts
通常解析位置参数,但如果在 ARGS,getopts
解析那些代替。
getopts
可以通过两种方式报告错误。如果optstring的第一个字符是冒号,则使用静默错误报告。在正常操作中,当遇到无效选项或缺少选项参数时会打印诊断消息。如果变量OPTERR
设置为 0,即使optstring的第一个字符不是冒号,也不会显示错误消息。如果看到无效选项,则
getopts
放置 '?' 进入name,如果不是静默,则打印错误消息并取消设置OPTARG
。如果getopts
是静默,则将找到的选项字符放入,OPTARG
并且不打印诊断消息。如果未找到必需的参数,并且getopts
不是无声的,则在name 中放置一个问号 ('?') ,OPTARG
未设置,并打印诊断消息。如果getopts
是无声的,则在name 中放置一个冒号 (':')并OPTARG
设置为找到的选项字符。
注意:
选项字符串中的前导冒号 puts getopts
进入静默模式;它不会生成任何错误消息。
描述没有提到任何关于可选选项参数的内容。
我假设您追求的功能类似于:
script -ffilename
script -f
Run Code Online (Sandbox Code Playgroud)
其中标志f
( -f
) 可选择接受一个参数。bash
的getopts
命令不支持此操作。POSIX 函数getopt()
几乎不支持这种表示法。实际上,在 POSIX 下,只有命令行上的最后一个选项可以有一个可选参数。
部分地,请参阅在shell 脚本中使用以获取长短命令行选项getopts
bash
。
GNU getopt
(单数!)程序是一个复杂的野兽,它支持长选项和短选项并支持长选项的可选参数(并使用 GNU getopt(3)
。跟踪它的来源很有趣;die.net 页面上的链接是错误的;你会在ftp://ftp.kernel.org/pub/linux/utils/util-linux下的子目录中找到它(没有-ng
)。我没有在http://www.gnu.org 找到一个位置/或包含它的http://www.fsf.org/。
对于bash,这是我最喜欢的解析/支持cli参数的方法。我使用了getopts,令人沮丧的是它不支持长选项。我很喜欢它的其他工作方式-特别是对于内置功能。
usage()
{
echo "usage: $0 -OPT1 <opt1_arg> -OPT2"
}
while [ "`echo $1 | cut -c1`" = "-" ]
do
case "$1" in
-OPT1)
OPT1_ARGV=$2
OPT1_BOOL=1
shift 2
;;
-OPT2)
OPT2_BOOL=1
shift 1
;;
*)
usage
exit 1
;;
esac
done
Run Code Online (Sandbox Code Playgroud)
简短,简单。工程师的最好朋友!
我认为可以对其进行修改以支持“-”选项。
干杯=)