我正在努力使脚本具有这种行为:
- 我想传递这样的选项,
./script -ab
就像./script -a -b
- 并具有以下逻辑:“a & b -> c”、“a & c -> c”、“b & c -> c”(单个选项正常运行)
- 另外,我希望该脚本在没有任何选项的情况下调用脚本时回退到函数(例如帮助函数)
这是一些例子:
#!/usr/bin/env bash
if [[ ${#} -eq 0 ]]; then
echo "Default function"
else
while getopts ":a:b:c:" opt; do
case ${opt} in
a) echo "a" ;;
b) echo "b" ;;
c) echo "c" ;;
*) echo -e "Invalid option: ${@}" ;;
esac
done
fi
任何帮助表示赞赏
答案1
最简单的方法可能是为每个选项设置标志,然后在循环之后检查 A 和 B 的标志是否都已设置,如果设置了则启用 C。
但是您可以将其建模为位图,其中 A 和 B 各占一位,而 C 是这两个位均已设置的状态。因此 A=01、B=10、C=11 加上两个位均被清除的默认状态。 (这些状态对应于十进制或十六进制的默认=0、A=1、B=2、C=3。)然后,当看到相应的选项时,只需设置适当的位即可。
就像这样:
#!/usr/bin/env bash
mode=0
while getopts "abc" opt; do
case ${opt} in
a) mode=$(( mode | 0x01 )) ;; # set rightmost bit
b) mode=$(( mode | 0x02 )) ;; # set leftmost bit
c) mode=$(( mode | 0x03 )) ;; # set both bits
*) exit 1 ;;
esac
done
echo "chosen mode is $mode (0 = default, 1 = a, 2 = b, 3 = c)"
请注意,您在文本中提到了-A
和,但您的脚本有和。关心字母大小写,所以它们不一样。另外,冒号将选项标记为接受参数,但您似乎不需要它。-b
a
b
getopts
getopts a:b:c:
答案2
(编辑以处理问题中的新请求)
你们非常接近。下面是我做过的事情。乍一看有点复杂,但它是一系列步骤设置默认值、解析命令行、检查错误的选项值或组合,然后编写主例程的脚本:
#!/usr/bin/env bash
# defaults for options
help=n
opt_a=1
opt_b=production
opt_c=0
# if no options from my user, print help message only
if [[ $# -lt 1 ]]; then help=y; fi
# parse command line
while getopts ':ha:b:c' OPTION; do
case "${OPTION}" in
h) help=y ;;
a) opt_a="${OPTARG}" ;;
b) opt_b="${OPTARG}" ;;
c) opt_c=1 ;;
\?) echo "$0: Error: Invalid option: -${OPTARG}" >&2 ; exit 1 ;;
:) echo "$0: Error: option -${OPTARG} requires an argument" >&2 ; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# request for help overrides other actions
if [[ ${help} == 'y' ]]; then
# put code here to print a USAGE message
exit 0
fi
# check and error out on bad options from my user
# check -b:
case "$opt_b" in
production) ;;
staging) ;;
qa) ;;
*) echo "$0: Error: unknown argument -b \"${opt_b}\", exiting" >&2 ; exit 1 ;;
esac
# script does its work starting from here
调用 with将按预期script-name -c -b qa
解析选项-b
和,并且也将起作用。-c
script-name -cb qa
我只给出了一个检查选项的例子(为了使答案简单);通常会有更多的代码来检查每个选项并响应合法和非法的选项组合。我通常将这些代码行塞入子例程中,这样它们就不会处于脚本主要工作流程的中间。