2

在 bash 脚本中,我想从配置文件加载设置并使用命令行选项覆盖各个设置。如果在配置文件和命令行中都指定了设置,则命令行设置应优先。

您如何确保在其他 getopts 块之前加载配置文件?这是我所拥有的:

#!/bin/bash
# ...

while getopts “c:l:o:b:dehruwx” OPTION
do
   case $OPTION in
      c)  
         echo "load"
         CONFIG_FILE=$OPTARG
         # load_config is a function that sources the config file
         load_config $CONFIG_FILE
         ;;  
      l)  
         echo "set local"
         LOCAL_WAR_FILE=$OPTARG
         ;;  

# ...

   esac
done
shift $(($OPTIND - 1))

无论我为 -c 选项放置处理程序的顺序如何,它总是在设置其他选项之后加载配置文件。这使得将配置文件设置与命令行选项合并更加痛苦。

4

2 回答 2

9

每次调用getopts总是处理“下一个”选项(由检查确定$OPTIND),因此您的while-loop 必须按照它们出现的顺序处理选项。

由于您希望-c被其他选项部分取代,即使它出现在命令行之后,您也可以采取一些方法。

一种是循环两次选项:

#!/bin/bash
# ...

optstring='c:l:o:b:dehruwx'

while getopts "$optstring" OPTION
do
   case $OPTION in
      c)
         echo "load"
         CONFIG_FILE=$OPTARG
         # load_config is a function that sources the config file
         load_config $CONFIG_FILE
   esac
done

OPTIND=1

while getopts "$optstring" OPTION
do
   case $OPTION in
      l)  
         echo "set local"
         LOCAL_WAR_FILE=$OPTARG
         ;;
      # ...
   esac
done
shift $(($OPTIND - 1))

-c 另一种是将选项保存在不会覆盖的变量中,然后将它们复制过来:

#!/bin/bash
# ...

while getopts c:l:o:b:dehruwx OPTION
do
   case $OPTION in
      c)
         echo "load"
         CONFIG_FILE=$OPTARG
         # load_config is a function that sources the config file
         load_config $CONFIG_FILE
         ;;  
      l)  
         echo "set local"
         LOCAL_WAR_FILE_OVERRIDE=$OPTARG
         ;;
      # ...
   esac
done
shift $(($OPTIND - 1))

LOCAL_WAR_FILE="${LOCAL_WAR_FILE_OVERRIDE-${LOCAL_WAR_FILE}}"

(或者,相反,配置文件可以设置类似的选项LOCAL_WAR_FILE_DEFAULT,然后你会写LOCAL_WAR_FILE="${LOCAL_WAR_FILE-${LOCAL_WAR_FILE_DEFAULT}}"。)

另一种选择是要求-c,如果存在,首先来。您可以通过自己先处理它来做到这一点:

if [[ "$1" = -c ]] ; then
   echo "load"
   CONFIG_FILE="$2"
   # load_config is a function that sources the config file
   load_config "$CONFIG_FILE"
   shift 2
fi

然后在您的主while循环中,只需-c打印一条错误消息即可。

另一个只是简单地记录您现有的行为并将其称为“功能”。很多 Unix 实用程序都有后面的选项取代早期的选项,所以这种行为并不是真正的问题。

于 2013-02-26T18:20:23.340 回答
1

假设您的配置文件包含程序的默认选项,您应该始终默认使用这些选项,除非它们被等效的命令行选项覆盖。这是合理的。在您的情况下,只需首先获取/加载配置文件,然后解析命令行选项 - 并parseopts根据需要在循环中为它们分配新值。

于 2013-02-26T00:29:17.227 回答