【问题标题】:getopts in bash, script was working before and now I'm baffledbash中的getopts,脚本以前可以工作,现在我很困惑
【发布时间】:2015-11-07 22:48:18
【问题描述】:

所以我的 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 之一)除了它确定正在执行的主要操作之外,这并不重要。

现在有问题的 getopts 事情。这以前有效,现在不行了。我们的目标是,如果有人想输入数据,他们可以使用以下 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 上做错了什么?以前可以正常工作,但现在....根本不工作!

【问题讨论】:

    标签: bash getopts


    【解决方案1】:

    有一点值得注意:如果你的脚本已经调用了一次getopts,另一个getopts调用将在所有选项之后开始,因此实际上什么都不做;在每个后续的 getopts 调用之前将 OPTIND 重置为 1 以让它们重新处理所有选项。

    你的代码有两个语法错误,一般来说值得清理:

    • 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
    

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      相关资源
      最近更新 更多