如何让Bash脚本接收完整短选项而非拆分后续字符为参数
问题根因
你遇到的现象是getopts的默认行为导致的:
- 你的
getopts配置中i:表示-i选项必须接收一个参数,当输入-in hello时,-in是同一个命令行参数(token),getopts会直接把i后面紧跟的n作为-i的参数值,这种情况下n不会被识别为独立的选项,自然不会触发非法选项的\?分支。 - 另外你当前配置里
u:表示-u也需要接收参数,但你代码中处理-u的逻辑没有用到$OPTARG,如果这不是你的预期,需要先把u后面的冒号删掉。
解决方法
如果你要求所有选项必须和参数分开写(也就是-i hello合法,-ihello/-in hello非法),可以在处理-i的分支中增加参数合法性校验,检查-i是不是单独作为一个独立的命令行参数存在,不是的话直接调用help。
修改后的完整代码如下:
#!/bin/bash # 先实现你的help函数,这里给个示例 help(){ echo "用法: $0 [-i 输入参数] [-u 输入参数]" >&2 exit 1 } run(){ local OPTIND opt iinput uinput while getopts ":i:u:" opt; do case $opt in i) # 校验-i是不是单独的参数,避免选项和参数/其他非法选项连写 if [[ "${@:$((OPTIND-1)):1}" != "-i" ]]; then help fi echo "Typed -i and $OPTARG" iinput="$OPTARG" ;; u) # 如果你不需要-u带参数,把optstring里u后面的冒号去掉,同时删掉这行校验 if [[ "${@:$((OPTIND-1)):1}" != "-u" ]]; then help fi echo "Typed -u and $OPTARG" uinput="$OPTARG" ;; \? | :) # 加:分支处理选项缺参数的场景,统一触发help help ;; esac done shift $((OPTIND -1)) echo "$iinput" } run "$@"
补充说明
- 如果你不需要
-u带参数,只需要把getopts ":i:u:" opt改成getopts ":iu:" opt即可,同时可以去掉-u分支里的校验逻辑。 - 所有传递给函数的参数建议用双引号包裹
"$@",避免参数带空格时解析异常。
内容的提问来源于stack exchange,提问作者user96931
相关产品推荐
相关产品推荐

