这是写opts的正确方法吗?

时间:2012-10-11 18:39:21

标签: linux bash shell command-line getopts

这是获取和设置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

1 个答案:

答案 0 :(得分:1)

如果要解析选项,可以使用两个选项:

  1. getopts(你可以查看这个的getopts教程)
  2. 手动解析(我将在此处介绍)
  3. 使用getopts可能更容易,但不够灵活。您的代码大部分都是正确的,但不适合更一般的选项解析。

    1. 正如chepner所述,while truewhile :相同。前者是首选,因为它立即直观地做了什么。这是我们所说的bash,而不是perl。不需要不必要的混淆。
    2. while true不是解析选项的良好循环终止条件。如果你考虑一下,它就不会告诉你循环在做什么。我必须一直到你的最后一个案例来了解发生了什么。正确的循环终止条件是当你用完命令行参数时。
    3. 我们的循环没有立即显示任何形式的均匀循环。我必须阅读每个案例,看看你是否正在改变位置参数数组。由于您将在每次迭代时至少执行一次shift,所以请执行此操作。
    4. 使用*)来检查循环终止并不是一个好主意。空字符串将匹配:

      ./ foo.sh --option1“” - option2 123

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

    5. 最后一点:您应该引用所有变量,除非您确定它们不包含空格。 bash中的空格分裂发生在变量替换之后,因此空间可以真正搞砸你。如果你不确定,请引用它。
    6. 您的代码的修订版可以是:

      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