【问题标题】:Access second argument in getopts option using bash使用 bash 访问 getopts 选项中的第二个参数
【发布时间】:2014-03-04 11:28:08
【问题描述】:

几天前已经问过与此相关的问题here

但这一次条件不同,有以下使用getopts的bash脚本

#!/bin/bash
ipaddr=""
sysip=""
msgType=""
sshTimeout=""
bulbIndex=""
bulbstate=""
while getopts ":ht:d:A:r:s:m:" OPTION
do
    case $OPTION in
        h)
            usage $LINENO
            ;;

        t)
            let "t_count += 1"
            ipaddr="${OPTARG}"
            echo -e $ipaddr
            ;;

        d)
            let "d_count += 1"
            echo "Not supported"
            exit 0
            ;;

        A)
            let "A_count += 1"
            bulbIndex="${OPTARG}"  #  After -A option firsr argument is bulb index and second is state off/on
            bulbstate=$3
            printf "Set %s state on %s bulb\n" $bulbstate $bulbIndex
            ;;

        r)
            let "r_count += 1"
            sysip="${OPTARG}"
            echo -e $sysip
            ;;

        m)
            let "m_count += 1"     #message type 1:text 2:number 3:Text&number
            msgType="${OPTARG}"
            echo -e $msgType
            ;;

        s)
            let "s_count += 1"
            sshTimeout="${OPTARG}"
            echo -e $sshTimeout
            ;;

        ?)
            echo -e "wrong command sysntax"
            exit 0
            ;; 
    esac
done

上面的脚本对除-A 选项之外的所有选项都正常工作。它有什么问题让你从下面的脚本执行步骤中知道

$ ./sample.bash -A 3 OFF
Set OFF state on 3 bulb

这是预期的输出,但是当我给出多个选项时,它的行为就会出错

$ ./sample.bash -t 192.168.0.1 -r 192.169.0.33 -A 3 OFF
192.168.0.1
192.169.0.33
Set -r state on 3 bulb

在这里,我希望OFF 而不是-r,显然它会给出这个输出,因为这次不是$3,而是$7,但我的问题是我如何通知脚本它现在是$7 而不是$3 .

$ ./sample.bash -t 192.168.0.1 -A 3 OFF -r 192.169.0.33 -m 1
192.168.0.1
Set -A state on 3 bulb

这次在-A 之后,所有选项都被丢弃,再次-A 而不是OFF

如何在-A 选项的任何序列中正确访问-A 选项之后的两个参数?

还有任何人对问题有疑问,请告诉我,坦率地说,它的任何解决方案都意味着非常简单或困难,但目前我不知道。

【问题讨论】:

    标签: linux bash shell getopts


    【解决方案1】:

    getopts 每个选项只接受一个参数。如何将两个参数传递给 -A 内引号,然后在您的 case 语句中将它们分开?

    A)
        let "A_count += 1"
        bulbIndex=${OPTARG% O*}
        bulbstate=${OPTARG#* }
        printf "Set %s state on %s bulb\n" $bulbstate $bulbIndex
        ;;
    

    然后调用:

    $ ./sample.bash -t 192.168.0.1 -r 192.169.0.33 -A "3 OFF"
    

    给:

    192.168.0.1
    192.169.0.33
    Set OFF state on 3 bulb
    

    如果你不能使用引号,那么如果你可以确保 -A 是最后使用的选项,那么你可以使用 OPTARG 来获取数字,然后只需单独获取最后一个参数。

    A)
        let "A_count += 1"
        bulbIndex="${OPTARG}"
        bulbstate=${@: -1}
        printf "Set %s state on %s bulb\n" $bulbstate $bulbIndex
        ;;
    

    【讨论】:

    • 感谢您的回答,您是对的,但我必须使用-A 3 4 而不是您的
    • 不确定你的意思,你是说你应该能够使用 -A 与任意数量的bulbIndex 参数?例如-A 3 4 5 OFF ?
    • 不是,我在之前的评论中的错误是 -A 3 OFF 而不是 -A 3 4-A 选项后必须只有两个参数。
    • 添加了另一种方法 - 但它仅在 -A 是最后使用的选项时才有效。正如我在答案中所说,getopts 只接受每个选项的一个参数,因此添加第二个参数必然有点麻烦。或者,有第二个论点怎么样?例如 -A 表示 ON,-X 表示 OFF 或类似的。
    • 这是这样做的方法,但必须 -A 是最后一个选项,在我的情况下不是这样。还有一些人在玩OPTIND 可能会得到它。在我这边仍然尝试得到它,感谢朋友坚持我的问​​题来解决它。
    【解决方案2】:

    终于在玩了OPTIND之后找到了获取方法。修改getopts中的-A选项如下

    A)
        let "A_count += 1"
        let "index += $OPTIND" # where initial value of index is 2
    
        bulbstate=${!index}
    
        bulbIndex="${OPTARG}"
    
        printf "Set %s state on %s bulb\n" $bulbstate $bulbIndex
    
        ((OPTIND++))
        ;;
    

    【讨论】: