bash脚本中使用getopt处理长选项时赋值失败的问题咨询
bash脚本中使用getopt处理长选项时赋值失败的问题咨询
你好,我看到你遇到了一个挺奇怪的问题——同样用--been=xxx的方式传参,有的时候能正确给arg赋值,有的时候却只能拿到默认值。咱们一步步来捋清楚问题出在哪。
首先先把你的脚本和测试情况整理清楚:
你的脚本代码
#!/usr/bin/env bash arg="default" TEMP=$(getopt --long been: -n 'test.sh' -- "$@") eval set -- "$TEMP" while true ; do case "$1" in --been) echo 'in been option' arg="$2" shift;; --) echo 'in the end' shift ; break ;; esac done echo "$arg"
你的测试案例
- 测试1:执行
bash ./test.sh --been=xxyyzz,输出:in the end default - 测试2:执行
bash ./test.sh --been=xxxx,输出:in been option xxxx
问题分析
这里其实有两个关键问题:
- getopt调用缺少短选项声明:当你只使用长选项、没有短选项时,必须明确指定
-o ''(空的短选项列表)。部分系统的getopt版本如果没看到短选项声明,会默认尝试按短选项规则解析,导致--been=xxyyzz这种带=的长选项格式无法被正确识别,直接被当成普通参数处理,自然就走不到--been的分支里。 - shift次数错误:即使
getopt正确把--been=xxyyzz拆成--been和xxyyzz两个参数,你当前只执行了shift一次,只会跳过--been,下一次循环的$1会变成xxyyzz,这个值匹配不到任何case分支,正常来说会陷入无限循环,但你的测试1却走到了--分支,也侧面说明getopt根本没正确解析这个长选项。
解决办法
修改后的完整脚本如下:
#!/usr/bin/env bash arg="default" # 添加-o ''声明空短选项列表,确保长选项解析正常 TEMP=$(getopt -o '' --long been: -n 'test.sh' -- "$@") eval set -- "$TEMP" while true ; do case "$1" in --been) echo 'in been option' arg="$2" # 执行shift 2,跳过选项本身和它的参数 shift 2;; --) echo 'in the end' shift ; break ;; # 加个未知选项分支,避免遇到无法识别的参数时无限循环 *) echo "Unknown option: $1" shift;; esac done echo "$arg"
现在再测试bash ./test.sh --been=xxyyzz,就能得到预期输出:
in been option in the end xxyyzz
备注:内容来源于stack exchange,提问作者showkey
相关产品推荐
相关产品推荐

