代码之家  ›  专栏  ›  技术社区  ›  Nic Gibson

在bash中,如何确定一组变量中是否只有一个具有值?

  •  0
  • Nic Gibson  · 技术社区  · 5 年前

    DATE , URI URI_FILE . 它们包含使用 getopt :

    while getopts ":d:p:u:hFA" opt; do
    
       case $opt in
           d) DATE=$OPTARG;;
           u) URI=${OPTARG};;
           U) URI_FILE=${OPTARG};;
           F) FORCE=yes;;
           A) ALL=yes;;
    
       esac
    
    done
    

    如果这些变量中有一个以上被设置为任何值(它们是可选的命令行选项),我需要失败并返回一个错误。我完全不知道如何优雅地测试它。我有些东西看起来像:

    #!/bin/bash 
    
    if [[ -z "${URI+x}" ]]
    then
        URI_PRESENT=0
    else
        URI_PRESENT=1
    fi
    
    if [[ -z "${URI_FILE+x}" ]]
    then
        URI_FILE_PRESENT=0
    else
        URI_FILE_PRESENT=1
    fi
    
    if [[ -z "${DATE+x}" ]]
    then
        DATE_PRESENT=0
    else
        DATE_PRESENT=1
    fi
    
    
    ARGCOUNT=$((${DATE_PRESENT} + ${URI_FILE_PRESENT} + ${URI_PRESENT}))
    
    if (( ${ARGCOUNT} > 1 ))
    then
        echo "Only one of date, uri and uri-file may be supplied"
        exit 1
    fi
    

    必须有一个更干净的方法来做这件事。建议?我将至少增加更多的选择,这会很痛苦

    1 回复  |  直到 5 年前
        1
  •  2
  •   Ed Morton    5 年前

    创建一个由选项列表中每个互斥选项索引的关联数组,然后报告其大小是否大于1:

    #!/bin/env bash
    
    declare -A opts
    while getopts ":d:u:U:hFA" opt; do
        case $opt in
        d) DATE=$OPTARG
           opts["$opt"]=1;;
        u) URI=${OPTARG}
           opts["$opt"]=1;;
        U) URI_FILE=${OPTARG}
           opts["$opt"]=1;;
        F) FORCE=yes;;
        A) ALL=yes;;
        esac
        if (( ${#opts[@]} > 1 )); then
            echo "Only one of date, uri or uri-file may be supplied" >&2
            exit 1
        fi
    done
    

    这将允许同一选项的多个实例出现在命令行上,而不允许2个或更多不同选项的实例。

        2
  •  3
  •   John Kugelman dbush    5 年前
    counter=0
    [[ $DATE ]] && ((counter+=1))
    [[ $URI ]] && ((counter+=1))
    [[ $URI_FILE ]] && ((counter+=1))
    
    if ((counter > 1))
    then
        echo "Only one of date, uri and uri-file may be supplied" >&2
        exit 1
    fi
    
        3
  •  3
  •   wjandrea Geographos    5 年前

    mickp's comment :

    为什么不使用一个在每个 case

    实施:

    while getopts ":d:p:u:hFA" opt; do
       case $opt in
       d) DATE=$OPTARG
          ((count++));;
       u) URI=${OPTARG}
          ((count++));;
       U) URI_FILE=${OPTARG}
          ((count++));;
       F) FORCE=yes;;
       A) ALL=yes;;
       esac
       if ((count > 1)); then
           echo "Only one of date, uri or uri-file may be supplied" >&2
           exit 1
       fi
    done