/bin/sh自定义解析命令行参数出现shift: can't shift that many报错如何解决
问题根因
POSIX shell 中for arg do循环的迭代列表在循环启动时就已固定,是当时$@的静态拷贝。循环体内执行shift仅会修改当前shell环境的$@,不会改变for循环预设的迭代序列,因此会出现遍历到-P的参数值、循环次数超出预期、shift操作越界报错的问题。
解决方案
将for循环替换为while循环,动态判断剩余参数数量$#,每次手动取第一个参数$1处理,处理完成后执行shift更新参数列表,修改后的完整代码如下:
#!/bin/sh f= pattern= while [ $# -gt 0 ]; do arg="$1" shift case "$arg" in (-P) if [ -n "$1" ] ; then pattern="$1" shift else printf "\nError: -P needs an argument\n\n" >&2 exit 1 fi ;; (*) if [ -z "$f" ] ; then f="$arg" else printf "\nError: too many arguments: %s %s\n\n" "$f" "$arg" >&2 exit 1 fi ;; esac done # 可选补充:必填参数合法性校验 if [ -z "$f" ]; then printf "\nError: missing filename argument\n\n" >&2 exit 1 fi
效果验证
该实现支持任意参数顺序:
- 调用
./myscript file.txt -P "pattern"时,会正确识别f=file.txt,pattern=pattern - 调用
./myscript -P "pattern" file.txt时,同样会正确识别两个参数 - 多余参数、-P后无值、未传文件名的场景都会触发对应报错
内容的提问来源于stack exchange,提问作者Martin Vegter
相关产品推荐
相关产品推荐

