bash中的getopts,脚本之前正在工作,现在我感到很困惑

时间:2015-11-07 22:48:18

标签: bash getopts

所以我的bash脚本中有几个getopts。这是一个工作的例子。

FOUND=
SEARCH=
COUNT=0
while getopts "ips:flenkc" OPTION
do
case $OPTION in
        i)
                FOUND=1
                let "COUNT++"
                ;;
        p)
                FOUND=2
                let "COUNT++"
                ;;
        s)
                FOUND=3
                SEARCH=$OPTARG
                let "COUNT++"
                ;;
esac
done

稍后在一个case语句中检查count = 1(意味着,在调用中只使用以下一个,i,p和s)并不重要,除非它确定正在执行的主要操作。

现在有问题了。这在以前工作,现在不是。目标是使其如果有人想要输入数据,他们可以使用以下bash命令来执行此操作。

./programname -i -f Mary -l Sue -e smary@email.com -n 555-555-5555

当使用-i时,我们必须有-f,-l,-e和-n(对于名字,姓氏,电子邮件和号码)。 我正在使用的代码:警告,代码中充满了语法错误。如果您正在学习bash,我强烈建议您不要使用我在帖子中看到的任何内容。

if [ $FOUND == "1" ]
then
        echo "You have chosen to insert things."
        FIRST=
        LAST=
        EMAIL=
        NUMBER=
        while getopts "if:l:e:n:" OPTION
        do
        case $OPTION in
                f)
                        FIRST=$OPTARG
                        ;;
                l)
                        LAST=$OPTARG
                        ;;
                e)
                        EMAIL=$OPTARG
                        ;;
                n)
                        NUMBER=$OPTARG
                        ;;
        esac
        done

        if [[ -z $FIRST ]] || [[ -z $LAST ]] || [[ -z $EMAIL ]] || [[ -z $NUMBER ]]
            echo "Error!!! Some input is missing!!!"
            usage // display usage
        exit 1
        fi
        echo -e $FIRST"\t"$LAST"\t"$EMAIL"\t"$NUMBER >> contacts
fi

在此程序运行之前,但是现在,甚至没有一件事能让它输入FIRST,LAST,EMAIL和NUMBER(我尝试更改代码以查看它是否正在执行某些步骤)

我对getopts做错了什么?它之前工作正常,但现在......它根本不起作用!

1 个答案:

答案 0 :(得分:5)

前面值得注意的一件事:如果您的脚本已经调用getopts一次,则另一个getopts调用将在所有选项之后启动,因此无效地执行任何操作;在每次后续OPTIND调用之前将1重置为getopts,让他们重新处理所有选项。

您的代码既有语法错误,也值得清理:

  • if [[ -z ...语句缺少then
  • //之后的usage会导致语法错误 - 类似POSIX的shell使用#作为注释字符。
  • 由于这是bash脚本,因此请坚持使用[[ ... ]]一致(不需要[ ... ])和/或使用(( ... ))进行算术运算。
    • 具体来说,请避免使用[ ... == ... ],因为它将POSIX语法 - [ ... ]与特定于Bash的语法混合在一起 - ==(POSIX仅支持=)。
    • 如果您使用[ ... ],请务必双引号变量引用,以确保安全。
  • 无需多个[[ ... ]]表达式将它们组合在一起 - 在 [[ ... || ... || ... ]]中执行此操作。
  • 最好避免使用全大写的shell变量名称,以便avoid conflicts with environment variables and special shell variables
  • 使用>&2
  • 将错误消息输出到 stderr
  • 用双引号将整个参数括在echo -e中,以保护变量值免受可能不需要的扩展。

通常可以使用shellcheck.net来捕获语法错误。

总而言之,我们得到:

#!/usr/bin/env bash

# ... code that sets $found

# If you've already processed args. with getopts above,
# you must reset OPTIND to process them again.
OPTIND=1

if (( found == 1 )) # found is numeric, use arithmetic expression to compare
then
        echo "You have chosen to insert things."
        first= last= email= number= # don't use all-uppercase var. names
        while getopts "if:l:e:n:" option
        do
          case $option in
                f)
                        first=$OPTARG
                        ;;
                l)
                        last=$OPTARG
                        ;;
                e)
                        email=$OPTARG
                        ;;
                n)
                        number=$OPTARG
                        ;;
          esac
        done

        if [[ -z $first || -z $last || -z $email || -z $number ]]; then
            echo "Error!!! Some input is missing!!!" >&2
            usage # display usage
            exit 1
        fi
        echo -e "$first\t$last\t$email\t$number" >> contacts
fi