0

这是获取和设置 OPTS 的正确方法吗?

我希望能够接受很多选择,比如

./runthis.sh --option1 setuff --option2 setmorestuff

while :
do
        case $1 in
                -h | --help | -\?)
                        usage
                        exit 0
                        ;;
                -o | --option1)
                        O=$2
                        shift 2
                        ;;
                -z | --option2)
                        Z=$2
                        shift 2
                        ;;
                --) # End of all options
                        shift
                        break
                        ;;
                -*)
                        echo "WARN: Unknown option (ignored): $1" >&2
                        shift
                        ;;
                *)  # no more options. Stop while loop
                        break
                        ;;
        esac
done
4

1 回答 1

1

如果您想解析选项,您有两个现成的选项可供您使用:

  1. getopts(你可以查找这个的 getopts 教程)
  2. 手动解析(我将在这里介绍)

使用 getopts 可能更容易,但不够灵活。您的代码大部分是正确的,但不适合更一般的选项解析。

  1. 正如 chepner 所说,while truewhile :. 前者是首选,因为它可以立即直观地看到它在做什么。这是我们正在谈论的 bash,而不是 perl。不需要不必要的混淆。
  2. while true不是解析选项的良好循环终止条件。如果你仔细想想,它不会告诉你循环在做什么。我必须一直到你的最后一个案例才能了解发生了什么。正确的循环终止条件是当您用完命令行参数时。
  3. 我们的循环正在执行任何形式的统一循环并不是很明显。我必须阅读每个案例以查看您正在移动位置参数数组。由于您将shift在每次迭代中至少执行一次,因此请执行此操作。
  4. 绑定到#2,使用*)检查循环终止不是一个好主意。空字符串将匹配:

    ./foo.sh --option1 "" --option2 123

    如您所见,option2使用您的代码永远不会获得它的价值。幸运的是 #2 也会解决这个问题。

  5. 最后一点:您可能应该引用所有变量,除非您确定它们不会包含空格。bash 中的空格拆分发生在变量替换之后,所以空格真的会搞砸你。如果您不确定,请引用它。

您的代码的修订版本可能是:

while [ $# -gt 0 ]
do
        case "$1" in
                -h | --help | -\?)
                        usage
                        exit 0
                        ;;
                -o | --option1)
                        O="$2"
                        shift
                        ;;
                -z | --option2)
                        Z="$2"
                        shift
                        ;;
                --) # End of all options
                        shift
                        break
                        ;;
                *)
                        echo "WARN: Unknown option (ignored): $1" >&2
                        break
                        ;;
        esac
        shift
done
于 2012-10-30T03:24:03.297 回答