shell:在其余部分之前搜索一个命令行参数

时间:2016-03-15 18:29:36

标签: bash shell

我正在使用getopt读取命令行参数,而我正在使用.读取配置文件:

test.sh:

#!/bin/bash

set -- `getopt C:a:b:c: "$@"`

C="default.cfg"
. $C

while [ $# -gt 0 ]; do
    case "$1" in
    -a) cfg1="$2"; shift;;
    -b) cfg2="$2"; shift;;
    -c) cfg3="$2"; shift;;
    -C) C="$2"; #you'll see what this is for later
        shift;;
    --) shift;
        break;;
    -*) echo "invalid option";
        exit 1;;
    *) break;;
    esac
    shift
done

echo "cfg1 = $cfg1"
echo "cfg2 = $cfg2"
echo "cfg3 = $cfg3"

exit 0

default.cfg中:

cfg1=hello
cfg2=there
cfg3=friend

这一切都按预期工作:

$ ./test.sh
cfg1 = hello
cfg2 = there
cfg3 = friend
$ ./test.sh -b optional
cfg1 = hello
cfg2 = optional
cfg3 = friend

这个问题是我希望以下列方式对配置进行优先排序:

  1. 命令行上给出的选项
  2. -C选项
  3. 定义的配置文件中定义的选项
  4. 默认配置文件中定义的选项
  5. 所以,如果我有这个:

    test.cfg:

    cfg1=custom_file_1
    cfg2=custom_file_2
    

    我想得到这个:

    $ ./test.sh -b command_line -C test.cfg
    cfg1 = custom_file_1
    cfg2 = command_line
    cfg3 = friend
    

    我无法弄清楚如何加载默认配置文件,然后搜索-C的选项,然后加载自定义配置文件,覆盖默认值,然后搜索命令行参数AGAIN并覆盖再次配置。我是shell脚本的新手,所以请原谅我,如果我错过了一些明显的东西。

3 个答案:

答案 0 :(得分:1)

要覆盖变量,请尝试替换:

-C) C="$2";

with:

-C) . "$2";

并用:

调用它
./test.sh -C test.cfg -a command_line1 -b command_line2

更新:

对于任何顺序的选项,您可以尝试:

C="default.cfg"
. $C

while getopts C:a:b:c: OPTION
  do
    case $OPTION in
      a) cfg1_override=$OPTARG;;
      b) cfg2_override=$OPTARG;;
      c) cfg3_override=$OPTARG ;;
      C) . $OPTARG;;
      -) break;;
      -*) echo "invalid option";
          exit 1;;
      *) break;;
    esac
  done
shift $(($OPTIND - 1))

cfg1="${cfg1_override-${cfg1}}"
cfg2="${cfg2_override-${cfg2}}"
cfg3="${cfg3_override-${cfg3}}"

echo "cfg1 = $cfg1"
echo "cfg2 = $cfg2"
echo "cfg3 = $cfg3"

exit 0

基于Is it possible to specify the order getopts conditions are executed?

答案 1 :(得分:1)

您可以预处理参数并提取您正在寻找的值:

#!/bin/bash
args=$(getopt C:a:b:c: "$@")
eval set -- $args

conf="default.cfg"
source "$conf"

# pre-process the arguments and see if we can find -C    
found=0
for opt in "$@"; do
    if [[ $found -eq 1 ]] && [[ -f "$opt" ]]; then
        source "$opt"
        break
    fi
    if [[ "$opt" == "-C" ]]; then
        found=1
    fi
done

while [ $# -gt 0 ]; do
    case "$1" in
    -a) cfg1="$2"; shift;;
    -b) cfg2="$2"; shift;;
    -c) cfg3="$2"; shift;;
    -C) shift;; #don't do anything with this
    --) shift;
    break;;
    -*) echo "invalid option";
        exit 1;;
    *) break;;
    esac
    shift
done

echo "cfg1 = $cfg1"
echo "cfg2 = $cfg2"
echo "cfg3 = $cfg3"

exit 0

答案 2 :(得分:0)

第一个来源default.cfg。 比扫描-C选项的选项。找到后处理这个。 最后使用getopts并在getopts中找到它时跳过-C。