shell脚本使用getopts如何实现多标志传递、单标志多参数及默认逻辑
getopts 常见问题解法
首先你当前脚本的核心错误是在选项解析的case分支中直接执行了java命令,而getopts每次循环仅处理单个选项,这会导致多选项场景下重复执行命令,也无法实现参数组合。建议先将各个选项的参数存储到变量中,所有选项解析完成后再统一执行命令。
1. 支持同时传递多个标志
你尝试的c|t写法完全不符合getopts的执行逻辑,getopts每轮循环只会返回一个匹配到的选项,多个选项会逐轮循环处理。正确实现如下:
#!/bin/bash file="你的jar包路径.jar" # 初始化默认参数 classname=".*" tag="regression" usage() { echo "用法: $0 [-c 类名] [-t 标签]" exit 1 } while getopts c:t: option ; do case $option in c) classname="$OPTARG" ;; t) tag="$OPTARG" ;; *) usage ;; esac done # 所有选项解析完成后统一执行命令 java -jar "$file" --fail-if-no-tests --include-classname "$classname" --scan-class-path "$file" --include-tag "$tag"
按以上写法执行runner.sh -c classname -t tagname即可同时生效两个参数。
2. 单个标志传递多个参数
原生getopts不直接支持单选项多参数,可通过两种方式实现:
方案1:多参数用引号包裹
执行命令时将多个参数用引号包裹为单个参数,脚本内部分割使用:
# 执行示例:runner.sh -g "arg1 arg2 arg3" while getopts c:t:g: option ; do case $option in g) # 转成数组使用 g_args=($OPTARG) echo "获取到的g参数列表:${g_args[@]}" ;; # 其他选项省略 esac done
方案2:自动识别后续非选项参数
如果不想加引号,可以手动移动OPTIND指针收集后续所有非-开头的参数:
# 执行示例:runner.sh -g arg1 arg2 arg3 while getopts c:t:g option ; do case $option in g) g_args=() # 收集所有-g后面的非选项参数 while [[ $OPTIND -le $# && ${!OPTIND} != -* ]]; do g_args+=("${!OPTIND}") ((OPTIND++)) done echo "获取到的g参数列表:${g_args[@]}" ;; # 其他选项省略 esac done
3. 未提供任何标志时执行默认逻辑
不要用*匹配实现无参数逻辑,*的作用是捕获未知选项,两者场景完全独立。可以通过标记变量判断是否传入过有效选项:
#!/bin/bash file="你的jar包路径.jar" classname=".*" tag="regression" # 标记是否传入过选项 has_option=0 usage() { echo "用法: $0 [-c 类名] [-t 标签]" exit 1 } while getopts c:t: option ; do has_option=1 case $option in c) classname="$OPTARG" ;; t) tag="$OPTARG" ;; *) usage ;; esac done # 无任何选项时走默认逻辑 if [[ $has_option -eq 0 ]]; then echo "未传入任何选项,执行默认逻辑" java -jar "$file" --fail-if-no-tests --include-classname '.*' --scan-class-path "$file" --include-tag regression else java -jar "$file" --fail-if-no-tests --include-classname "$classname" --scan-class-path "$file" --include-tag "$tag" fi
以上实现中,传入未知选项会直接触发usage退出,不会和无参数默认逻辑混淆。
内容的提问来源于stack exchange,提问作者pk786
相关产品推荐
相关产品推荐

